Haskell FlatMap

15

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

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

这个实现了“map”部分但没有实现“flat”部分。
我所做的大多数修改都导致令人沮丧且信息相对较少。

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

错误。

我错过了什么?


3
顺便提一句,有一篇维基百科的文章介绍了"occurs check"是什么:http://en.wikipedia.org/wiki/Occurs_check - jrockway
1个回答

24
当您指定的类型签名与函数的实际类型不匹配时,就会出现像这样的错误。由于您没有展示导致错误的代码,我只能猜测,但我认为您将其更改为以下内容:
flatmap _ [] = []  
flatmap f (x:xs) = f x ++ flatmap f xs

恰好,这是完全正确的。然而,如果你忘记还要改变类型签名,将会发生以下情况:
类型检查器看到你在f xflatmap f xs的结果上使用了++。由于++用于两个相同类型的列表,类型检查器现在知道这两个表达式都必须求值为同一类型的列表。同时,类型检查器也知道flatmap f xs将返回一个[a]类型的结果,所以f x也必须具有[a]类型。然而,在类型签名中它说f具有t -> a类型,因此f x必须具有a类型。这导致类型检查器得出[a] = a的结论,这是一种矛盾,导致了您看到的错误消息。
如果你把类型签名改成flatmap :: (t -> [a]) -> [t] -> [a](或者删除它),就可以正常运行了。

如果您不指定类型签名,有时也会发生这种情况。 - Martijn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接