2014-05-21 41 views
1

谁能告诉我哪里出了问题?米兰达类型错误

b f x = f x (f x) 

我的理解是:因为f在左侧有一个参数,但在右侧有两个参数?

更详细的解释?

+1

'f'不会“在左边带参数”。 'x'不是LHS中'f'的参数。 – user2407038

回答

2

让我们尝试构建类型:

b :: ... ? 

我们至少有两个参数,所以让我们改变b相应:

b :: a -> c -> d 

b右手边认为,f是一个函数。让我们首先关注的只有第一个参数:

f :: c -> e 

到现在为止,一切都适合相当不错:列表的第一个参数具有相同的类型B的第二个参数。让我们继续在右侧。

f x (f x) 

如果我们把f x _,我们必须假设ee :: 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

编译器试图推断出f的类型。首先它看到f采用参数x和另一个参数(f x),现在我们将替换为y。因此,当编译器看到类似f x y的东西时,它推断f的类型为a -> b -> c,其中x :: ay :: bf x y :: c。然后它检查y更接近,看到它的类型更具体地b -> c,因为它已经知道f必须有第二个参数。所以现在可以确定b ~ b -> c。这是它必须停止的地方,b怎么样也是b -> c?如果它一直代替b ~ b -> c,它会有一个无限递归试图找出什么类型b是!这显然不能工作,所以它会抛出一个编译错误,说它不能构造无限类型b = b -> c(注意:错误消息可能使用与bc不同的名称)。该错误消息我得到的实际上是相当有帮助的:

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”。