Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 如何使用类型以及编译器为什么抱怨无限类型?_Haskell - Fatal编程技术网

Haskell 如何使用类型以及编译器为什么抱怨无限类型?

Haskell 如何使用类型以及编译器为什么抱怨无限类型?,haskell,Haskell,我有以下类型: newtype Moi s a = Moi { runMoi :: s -> (a, s) } 数据构造函数需要一个函数作为参数,它应该返回一个元组 我尝试了以下几点: *OwnState> :t Moi (+1) 编译器抱怨: <interactive>:1:6: error: * Occurs check: cannot construct the infinite type: s ~ (a, s) Expected t

我有以下类型:

newtype Moi s a =
  Moi { runMoi :: s -> (a, s) }  
数据构造函数需要一个函数作为参数,它应该返回一个元组

我尝试了以下几点:

*OwnState> :t Moi (+1)
编译器抱怨:

<interactive>:1:6: error:
    * Occurs check: cannot construct the infinite type: s ~ (a, s)
      Expected type: s -> (a, s)
        Actual type: (a, s) -> (a, s)
    * In the first argument of `Moi', namely `(+ 1)'
      In the expression: Moi (+ 1)
类型
a
必须约束为
Num
typeclass

因此,当我编写
Moi(+1)
时,将会发生什么,类型将如何替换

让我们分析错误消息,作为下一步:

Occurs check: cannot construct the infinite type: s ~ (a, s)
Tilde表示
~
类型相等,以及编译器如何得出
s
(a,s)
具有相同类型的结论

我想,上面示例的类型替换是这样工作的:

n -> n "Type of (+1)
|    |
s -> (a, s)
然后
s
变成
(a,s)
,证明
s~(a,s)
为真

(a, s) -> (a, s)
但我不明白,为什么它是无限型的

但我不明白,为什么它是无限型的

因为
s
同时出现在类型相等的左侧和右侧
~
,这是以递归方式出现的。经过一次替换后,我们有:

s ~ (a,s)
但请注意,
(a,s)
中的
s
也应替换,因此:

s ~ (a,s) ~ (a,(a,s)) ~ (a,(a,(a,s))) ~ ...
因此,为了构造这个类型,它将导致一个具有无限嵌套的2元组的类型。Haskell无法处理此类类型

Moi(+1)
与此“状态单子”的规格不匹配。您可能希望使用:

Moi (\x -> (x,x+1))
或:


它是无限的,因为
s
出现在
~
的左侧和右侧,而不是语义部分。因此,在一次替换之后,它是
s~(a,s)~(a,(a,s))
,等等。
s~(a,s)
不是真的——统一在“发生检查”步骤中失败。实际上,没有任何类型的
T
(a,T)
仍然是相同的类型:第二个类型直观地包含一个额外的
a
。这就像求解数字的
n=n+1
:它没有解,除非你以某种方式允许“无穷大”作为数字。@Willem Van Onsem你能给我这样的学习者演示一下如何替换类型吗。我看到了很多案例,替代是如何工作的,但不确定我是否正确。
Moi (\x -> (x,x+1))
Moi (ap (,) (1 +))