传递函数到函数生成无限类型

时间:2017-03-18 09:40:28

标签: haskell

我犯了一个错误包并写了这样一个函数:

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并解释我,因为我是个假人。

1 个答案:

答案 0 :(得分:6)

doWork f x = f f x

doWork有两个参数,fx

f f x

我们使用两个参数调用f,因此f必须是函数。

f :: a -> b -> c

现在,abc是什么?好吧,c是整个事物的结果类型。 bx的类型。 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 -> ca定义为提及自身的类型 - 无限类型循环。这是不允许的。

另一方面,如果我们有

f (f x)

然后f是一个1参数函数

f :: a -> b

由于内部的输出 - f作为输入传递给外部 - f,因此两种类型必须相同:a == b

f :: b -> b

这是一个非常明智的类型。所以这里没问题。