谁能告诉我哪里出错?
b f x = f x (f x)
我的理解是:因为左边的f
有一个参数,但右边有两个参数?
更详细的解释?
答案 0 :(得分:2)
让我们尝试构建该类型:
b :: ... ?
我们至少有两个参数,因此我们可以相应地更改b
:
b :: a -> c -> d
b
的右侧表明f
是一个函数。让我们首先关注第一个论点:
f :: c -> e
到目前为止,一切都很合适:list的第一个参数与b的第二个参数具有相同的类型。让我们继续在右边。
f x (f x)
如果我们采用f x _
,我们必须假设e
是e :: k -> l
,也就是说,我们采取另一个论点。我们现在有
f :: c -> k -> l
现在看一下f
第二个参数的类型。它的类型应该是f x
:
f x :: k -> l
所以k = k -> l
。这是一种无限类型,我们也可以通过查看ghci的错误消息来看到:
Prelude> let b f x = f x (f x) <interactive>:2:18: Occurs check: cannot construct the infinite type: t1 = t1 -> t0 In the return type of a call of `f' Probable cause: `f' is applied to too few arguments In the second argument of `f', namely `(f x)' In the expression: f x (f x)
类型检查器放弃,因为无法构造无限类型。最后,由于您对不同数量的参数应用f
,因此会发生这种情况。
答案 1 :(得分:1)
编译器尝试推断f
的类型。首先,它看到f
采用参数x
和另一个参数(f x)
,现在我们将其替换为y
。因此,当编译器看到f x y
之类的内容时,它会推断f
的类型为a -> b -> c
,x :: a
,y :: b
和f x y :: c
。然后它检查y
更接近,看到它的类型更具体b -> c
,因为它已经知道f
必须有第二个参数。所以它现在可以确定b ~ b -> c
。这就是它必须停止的地方,b
怎么也可以b -> c
?如果它继续替换b ~ b -> c
,它将有一个无限递归试图找出b
是什么类型!这显然无法工作,因此抛出一个编译错误,说它无法构造无限类型b = b -> c
(注意:错误消息可能使用与b
或c
不同的名称)。我得到的错误消息实际上非常有用:
Occurs check: cannot construct the infinite type: t1 = t1 -> t0
In the return type of a call of `f'
Probable cause: `f' is applied to too few arguments
In the second argument of `f', namely `(f x)'
In the expression: f x (f x)
这会告诉你问题的确切位置,即“(f x)
”,并告诉你可能的原因“f
适用于太少的参数”,说它“无法构造无限类型” t1 = t1 -> t0
”。