发生检查:无法构造无限类型:t0 = [t0]

时间:2014-12-28 22:43:10

标签: haskell

我试图使用foldr重写Data.List.group,这是我的代码:

group' :: (Eq a) => [a] -> [[a]]
group' xs = foldr pack' [[head xs]] (tail xs)
     where
        pack' x acc = if x == (head $ head acc)
           then x:(head acc)
           else [x]:acc

现在我收到了这些错误:

Occurs check: cannot construct the infinite type: t0 = [t0]
In the expression: x
In the first argument of `(:)', namely `[x]'
In the expression: [x] : acc

Occurs check: cannot construct the infinite type: t0 = [t0]
Expected type: [[t0]]
  Actual type: [[[t0]]]
In the second argument of `(:)', namely `acc'
In the expression: [x] : acc
In the expression:
  if x == (head $ head acc) then x : (head acc) else [x] : acc

两者都是指最后一行。

我很确定我错过了一些东西,但是我从来没有真正意识到自从包装的类型以来所做的一切。应该是:

pack` a -> [[a]] -> [[a]]

2 个答案:

答案 0 :(得分:2)

这一行:

then x:(head acc)

这一个

else [x]:acc

应该具有相同的类型。但是每个人都在列表的头部使用不同的类型。当它说“无法构造无限类型:t0 = [t0]”时,这意味着什么。如果a = [a],那么它必须是无限维列表。

答案 1 :(得分:1)

这是一个评论,它已经由chi提出,但也许它有助于实际显示:执行此类功能的“正确”方法是headtail ,可以用模式匹配代替。此外,if通常更好地重写为警卫。

group' :: (Eq a) => [a] -> [[a]]
group' (x0:xi) = foldr pack' [[x0]] xi
     where
        pack' xn acc@((x:xs):xss)
              | xn == x    = (xn : x : xs) : xss
              | otherwise  = [x]:acc

启用警告后,编译器会(正如它应该!)现在大声说你没有为空列表定义。所以你添加

group' [] = []

pack'内,我们确实不会发生空案例。