15

我是一个对 Haskell 感兴趣的初学者,我一直在尝试自己实现 flatmap (>>=) 以更好地理解它。目前我有

flatmap :: (t -> a) -> [t] -> [a]  
flatmap _ [] = []  
flatmap f (x:xs) = f x : flatmap f xs  

它实现了“地图”部分,但没有实现“平面”。
我所做的大多数修改都导致令人沮丧且相当无信息

Occurs check: cannot construct the infinite type: a = [a]  
    When generalising the type(s) for `flatmap' 

错误。

我错过了什么?

4

1 回答 1

24

当您指定的类型签名与函数的实际类型不匹配时,就会发生这样的错误。由于您没有显示导致错误的代码,我不得不猜测,但我认为您将其更改为如下所示:

flatmap _ [] = []  
flatmap f (x:xs) = f x ++ flatmap f xs

碰巧的是,这是完全正确的。但是,如果您忘记更改类型签名,则会发生以下情况:

类型检查器会看到您在f x和的结果上使用了 ++ flatmap f xs。由于++适用于相同类型的两个列表,类型检查器现在知道两个表达式都必须计算为相同类型的列表。现在类型检查器也知道flatmap f xs会返回 type 的结果[a],所以f x也必须有 type [a]。但是在类型签名中它说 f 有 type t -> a,所以f x必须有 type a。这会导致类型检查器得出结论,[a] = a这是一个矛盾并导致您看到的错误消息。

如果您将类型签名更改为flatmap :: (t -> [a]) -> [t] -> [a](或删除它),它将起作用。

于 2010-06-07T02:44:32.780 回答