我是一名对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'
错误。
我错过了什么?
答案 0 :(得分:21)
当您指定的类型签名与函数的实际类型不匹配时,会发生类似这样的错误。既然你没有显示导致错误的代码,我必须猜测,但我认为你把它改成了这样的东西:
flatmap _ [] = []
flatmap f (x:xs) = f x ++ flatmap f xs
实际情况是完全正确的。但是,如果您忘记也更改类型签名,则会发生以下情况:
类型检查器看到您对f x
和flatmap f xs
的结果使用++。由于++
适用于两个相同类型的列表,因此类型检查器现在知道两个表达式都必须计算到相同类型的列表。现在,类型检查器也知道flatmap f xs
将返回[a]
类型的结果,因此f x
也必须具有类型[a]
。但是在类型签名中,它表示f的类型为t -> a
,因此f x
必须具有类型a
。这导致类型检查器得出结论[a] = a
这是一个矛盾并导致您看到的错误消息。
如果您将类型签名更改为flatmap :: (t -> [a]) -> [t] -> [a]
(或删除它),它将起作用。