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 +))