1

我是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.

有人可以帮忙吗?提前致谢

4

3 回答 3

6

foldr 的类型是

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

所以分裂

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

y并且y:x必须是相同的类型,这对任何人来说都是不可能的,x并且在列表yy:x总是比y.

我想你想做什么x:y

于 2012-10-10T15:21:04.680 回答
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与 type 相同[b],然后当然与 type 相同[[b]][[[b]]]等等。因此它抱怨“无限类型”。

于 2012-10-10T15:25:08.603 回答
1

我之前的帖子回答了您的问题,但在您发表评论后,我可以看到您需要一个按谓词拆分列表的函数。

您可以使用 GHC.Exts 模块中的 groupWith::Ord b => (a -> b) -> [a] -> [[a]] 并在您的例子:

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

但是,由于您提供的二进制函数,这将始终将提供的列表分成两个列表。

于 2012-10-10T16:05:51.947 回答