我犯了一个错误包并写了这样一个函数:
Prelude> doWork f x = f f x
我收到了编译错误:
<interactive>:3:16: error:
• Occurs check: cannot construct the infinite type:
t ~ t -> t1 -> t2
• In the first argument of ‘f’, namely ‘f’
In the expression: f f x
In an equation for ‘doWork’: doWork f x = f f x
• Relevant bindings include
x :: t1 (bound at <interactive>:3:10)
f :: t -> t1 -> t2 (bound at <interactive>:3:8)
doWork :: (t -> t1 -> t2) -> t1 -> t2 (bound at <interactive>:3:1)
我想知道,为什么将f
应用于参数f
生成无限类型?这是递归吗?
正确的代码是:
Prelude> doWork f x = f (f x)
请注意,我刚刚开始学习haskell并解释我,因为我是个假人。
答案 0 :(得分:6)
doWork f x = f f x
doWork
有两个参数,f
和x
。
f f x
我们使用两个参数调用f
,因此f
必须是函数。
f :: a -> b -> c
现在,a
,b
和c
是什么?好吧,c
是整个事物的结果类型。 b
是x
的类型。 a
是...... f
本身的类型。但这意味着a == a -> b -> c
。如果您将a
替换为a -> b -> c
,则会获得
f :: (a -> b -> c) -> b -> c
但它仍然有a
。如果我们再次替换,我们得到
f :: ((a -> b -> c) -> b -> c) -> b -> c
f :: (((a -> b -> c) -> b -> c) -> b -> c) -> b -> c
等等,永远。问题是,a == a -> b -> c
将a
定义为提及自身的类型 - 无限类型循环。这是不允许的。
另一方面,如果我们有
f (f x)
然后f
是一个1参数函数
f :: a -> b
由于内部的输出 - f
作为输入传递给外部 - f
,因此两种类型必须相同:a == b
f :: b -> b
这是一个非常明智的类型。所以这里没问题。