Haskell学习者关于过滤器和放大器的一些小问题折

时间:2014-01-23 09:35:48

标签: haskell

这是我学习Haskell的第二天,我被一个问题严重困扰了。 我试图解决99 Haskell questions中的第八个问题 问题是编写一个名为“compress”的函数,其工作原理如下:

>compress "aaaabbbbccccddddd"
"abcd"
>compress [1,1,1,1,2,3,4,4,4,4]
[1,2,3,4]

这就是我写的:

compress :: (Eq a) => [a] -> [a]
compress [] = []
compress x = filter ( (head x) `notElem` ( compress $ tail x ) ) x

编译说:

  

无法匹配预期类型a -> Bool' with actual type Bool'

compress中,我试图以递归方式从头到尾拾取新元素。 (比如回溯也许?)

我的算法错了吗? 有没有其他方式以更易读的方式实现算法? (比如:在哪里放括号?或$

有人可以帮助我吗? 非常感谢。


感谢Lubomir的帮助,我通过以下方式纠正了我的代码:

  

compress'(x:xs)= x:compress'(dropWhile(== x)xs)

它有效!

谢谢大家,我感到被宠坏了! 你们真好!

我会继续学习Haskell!

3 个答案:

答案 0 :(得分:8)

  

是否有更可读的方法来实现算法   方式是什么?

import Data.List

compress :: Eq a => [a] -> [a]
compress = map head . group

map head . group基本上是\xs -> map head (group xs)group xs将创建一个列表列表,所有相等的连续元素在列表中组合在一起。然后,map head会根据需要将这些列表的head丢弃,然后根据需要将其余列入其中。

答案 1 :(得分:4)

该算法基本上没问题,但它没有进行类型检查。 filter的第一个参数应该是类型a -> Bool的函数 - 对于列表的元素,它应该告诉您是否将其抛出。你拥有的是一个Bool值。

可以使用不同的模式更好地实现函数的第二部分。这样您就可以放弃headtail函数。

compress [] = []
compress (x:xs) = x : compress (filter (/= x) xs)

此模式将x绑定到列表的第一个元素,xs是列表的尾部。该函数应在结果中包含x,并在已过滤的xs(从x中删除)中递归调用自身。

编辑:此功能不会执行问题请求。只应删除连续的重复项。这可以通过使用dropWhile而不是filter来修复,并稍微修改谓词函数。

答案 2 :(得分:2)

检查过滤器的签名:

Prelude> :t filter
filter :: (a -> Bool) -> [a] -> [a]

请注意,第一个参数必须是函数。现在检查paranthesis中表达式的类型。

Prelude> :t notElem
notElem :: Eq a => a -> [a] -> Bool

因此,notElem a b将返回Bool类型的值。

注意:我认为您可能误解了问题陈述。 aaabbbaaa的预期输出是多少? 我认为它应该是aba,因为问题被陈述为

  

消除连续重复的列表元素。

(强调我的)。