为什么可以使用“仅(+)”创建值?

时间:2019-08-05 20:10:02

标签: haskell type-parameter deriving

目前,我正在学习Haskell,并且坚持将类型实例化为类型类。我实际上不明白,为什么可以用import static org.mockito.ArgumentMatchers.any; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mockito; import org.mockito.junit.MockitoJUnitRunner; import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.HttpEntity; import org.springframework.http.HttpMethod; import org.springframework.http.ResponseEntity; import org.springframework.web.client.RestTemplate; @RunWith(MockitoJUnitRunner.class) public class MockitoTest { @Test public void test() { RestTemplate api = Mockito.mock(RestTemplate.class); ResponseEntity<?> response1 = Mockito.mock(ResponseEntity.class); ResponseEntity<?> response2 = Mockito.mock(ResponseEntity.class); Mockito.when(api.exchange(any(String.class), any(HttpMethod.class), any(HttpEntity.class), any(Class.class))).thenReturn(response1); Mockito.when(api.exchange(any(String.class), any(HttpMethod.class), any(HttpEntity.class), any(ParameterizedTypeReference.class))).thenReturn(response2); ParameterizedTypeReference mock = Mockito.mock(ParameterizedTypeReference.class); Assert.assertEquals(response1, api.exchange("", HttpMethod.GET, new HttpEntity(""), String.class)); Assert.assertEquals(response2, api.exchange("", HttpMethod.GET, new HttpEntity(""), mock)); } } 创建Maybe a类型的值。

我对此感到奇怪的问题是,可能将Maybe类型定义为Just (+)类型类的实例(请参见Haskell source),并且如果派生某个类型的实例,则所有该类型的值/数据构造函数的字段也必须是Eq类型类(here)的实例。

基于这些知识,以下代码不应是可编译或可执行的,因为函数不是Eq类型类的一部分:

Eq

但是GHCi实际上执行代码时不会抛出错误消息。如果然后尝试比较这两个值(这也是不可能的),则解释器会提出以下错误消息:

let a = Just (+)
let b = Just (-)

如果您创建自己的a == b <interactive>:24:1: error: * No instance for (Eq (Integer -> Integer -> Integer)) arising from a use of `==' (maybe you haven't applied a function to enough arguments?) * In the expression: a == b In an equation for `it': it = a == b 类型,也会发生此问题。

1 个答案:

答案 0 :(得分:12)

List的{​​{1}}实例看起来像这样(也就是说,Eq本质上被重写为这个):

Maybe

如果 deriving (Eq)instance (Eq a) => Eq (Maybe a) where ... 的成员,则可以理解为,然后然后也是a的成员。因此,制作Eq或您拥有什么完全没问题,如果参数不成立,就不会是Maybe a

从编译器的角度来看,这是一种对操作更有用的思考方式:解决Maybe (Int -> Int)约束,就足以解决Eq约束。所以当我们说

Eq (Maybe a)

编译器尝试解决Eq a。它使用a == b 实例将问题简化为Eq (Maybe (Integer -> Integer -> Integer)),然后在无可奈何的情况下放弃。因此,您看到错误消息抱怨Maybe没有实例,而不是提到Eq (Integer -> Integer -> Integer)