Haskell - 具有foldr函数的组列表元素

时间:2015-10-29 19:41:44

标签: list haskell fold

这是在Haskell中的一项任务。 我们的任务是使用foldr函数定义各种函数。

我们获得了一个类型:

group :: Eq a => [a] -> [[a]]

并被要求对其进行定义:

group [1,2,2,3,4,4,4,5] = [[1], [2,2], [3], [4,4,4], [5]]
group [1,2,2,3,4,4,4,5,1,1,1] = [[1], [2,2], [3], [4,4,4], [5], [1,1,1]]

这是我到目前为止所做的:

group = foldr (\x xs -> if x == head (head xs) then (x : head xs) : xs else (x : []) : (head xs) : xs )

但是当我尝试将其加载到ghci解释器中时,我收到以下错误消息:

Couldn't match type `[a0] -> [a]' with `[[a]]'
Expected type: [a] -> [[a]]
  Actual type: [a] -> [a0] -> [a]
In the return type of a call of `foldr'
Probable cause: `foldr' is applied to too few arguments
In the expression:
  foldr
    (\ x xs
       -> if x == head (head xs) then
              (x : head xs) : xs
          else
              (x : []) : (head xs) : xs)
In an equation for `group':
    group
      = foldr
          (\ x xs
             -> if x == head (head xs) then
                    (x : head xs) : xs
                else
                    (x : []) : (head xs) : xs)

如果有人能解释为什么我的代码没有像我期望的那样工作的原因,那将非常感激。 感谢。

2 个答案:

答案 0 :(得分:2)

我认为你走在正确的轨道上所以我会试着把你的想法写得更好一些。我想说的是:你应该将foldr的第一个参数拉入函数并再次进行模式匹配:

group :: Eq a => [a] -> [[a]]
group = foldr f undefined
  where f x []        = undefined
        f x (ys@(y:_):yss)
          | x == y    = undefined
          | otherwise = undefined

这应该做 - 现在你必须放入我放undefined的正确的东西:)

我稍后会回来并完成它

嗯,我猜你放弃了什么 - 无论如何这里是一个解决方案:

group :: Eq a => [a] -> [[a]]
group = foldr f []
  where f x []        = [[x]]
        f x (ys@(y:_):yss)
          | x == y     = (x:ys):yss
          | otherwise = [x]:ys:yss

以及一些例子:

λ> group []
[]
λ> group [1]
[[1]]
λ> group [1,1]
[[1,1]]
λ> group [1,2,1]
[[1],[2],[1]]
λ> group [1,2,2,3,4,4,4,5]
[[1],[2,2],[3],[4,4,4],[5]]

请注意f的模式并非详尽无遗(这没有问题 - 想想为什么) - 当然,如果您愿意,可以扩展它(如果您不同意group [] = []你必须。

答案 1 :(得分:1)

请注意,如果我没有错,这就是99个haskell问题中的问题9,可以在这里找到:https://wiki.haskell.org/99_questions/
对于每个问题,它都有一堆解决方案(通常),因为Carsten提供了一个很好的解决方案,你可以去那里看看其他解决方案,这样你就可以通过各种方式获得不同的想法!