使用foldr的Haskell错误

时间:2012-10-10 15:12:04

标签: haskell

我是哈斯凯尔的新手,并尝试了一些练习

我不明白产生的错误是什么以及产生错误的原因

split = foldr 
        (\x y -> y:x)
        [[]]

解释器上的错误如下

    Occurs check: cannot construct the infinite type: a0 = [a0]
    In the first argument of `(:)', namely `y'
    In the expression: y : x
    In the first argument of `foldr', namely `(\ x y -> y : x)'
Failed, modules loaded: none.
任何人都可以帮忙吗?提前致谢

3 个答案:

答案 0 :(得分:6)

折叠器的类型是

foldr :: (a -> b -> b) -> b -> [a] -> b

所以分裂

split = foldr (\x y -> y:x) [[]]

yy:x必须属于同一类型,这对任何xy都是不可能的,因为y:x总是更深一步在列表中比y

我想你想做x:y

答案 1 :(得分:2)

回想foldr(a -> b -> b) -> b -> [a] -> b的类型。这表示foldr期望一个函数将列表元素与最终结果类型的值组合在一起,从而产生结果类型的新值。

对于第一个参数,您已经为foldr函数\x y -> y:x,其中x将是列表元素,y是下一步的结果对;并且应用此lambda的结果应与y具有相同的类型。

(:)的类型是a -> [a] -> [a] - 也就是说,它会将单个元素附加到列表的头部。在表达式y:x中,您将采用“结果”类型的某些内容并将其用作结果列表的元素。

因此,GHC尝试推断结果类型b与类型[b]相同,当然它与类型[[b]]相同,并且{ {1}} ......等等。因此,它抱怨“无限型”。

答案 2 :(得分:1)

我之前的帖子回答了你的问题,但在你的评论之后我可以看到你想要一个用谓词分割你的列表的函数。

你可以使用groupWith :: Ord b => (a - > b) - > [a] - >来自模块GHC的[[a]]。在你的例子中,为它提供类型(a - > Bool)的函数:

groupWith even [1,2,3,4,5,6] yields [[1,3,5],[2,4,6]]

此外,丑陋但实现了你想要的“外出”类型的是:

split::Eq a => (a -> Bool) -> [a] -> [[a]]
split f ls = (ls \\ rl):rl:[]
    where rl = filter f ls

但由于你提供的二进制功能,这将始终只在两个列表中拆分提供的列表。