我是haskell的新手,我有一个问题(也就是家庭作业)。
所以,我有一个带有元组的列表 - 一个字符串和一个整数:
xxs :: [([Char], Integer)]
我需要知道xxs中有多少字符串以给定字符开头。 让我举例说明:
foo 'A' [("Abc",12),("Axx",34),("Zab",56)]
Output: 2
foo 'B' [("Abc",12),("Bxx",34),("Zab",56)]
Output: 1
到目前为止我的最佳尝试:
foo c xxs = length (foldl (\acc (x:xs) -> if x == c then c else x) [] xxs)
但是,当然,lambda表达式中有一些非常错误。
有什么建议吗? 感谢。
答案 0 :(得分:4)
你可以使用折叠,但我会建议另一种方式,它分三步解决问题:
map
使用此filter
所有不符合给定Char
length
显然,第一步是最难的,但不像看起来那么难。要做到这一点,你只需要以某种方式组合函数fst
和head
,或者更容易,两次映射。
你可以把它写成一个简单的单行,但也许你应该从let
开始:
foo c xxs = let strings = map ...
firstLetters = map ...
filteredLetters = filter ...
in length ...
答案 1 :(得分:2)
您的尝试存在一些问题:
您打算使用foldl
构建较短的列表,然后使用其长度。虽然有可能,filter
函数更适合该任务,因为@landei建议
foldl
可用于累积长度,而无需构建更短的列表。看到@WuXingbo的答案 - 他的答案是不正确的,但是一旦你意识到他的方法根本不需要length
,你应该很容易找到正确的解决方案。
与常识有些矛盾,在惰性语言中foldr
比foldl
更快且使用更少的内存。你应该问你老师为什么。
答案 2 :(得分:0)
我会把foo重写为
foo :: Char -> [(String, Int)] -> Int
foo c = length . filter ((==c).head.fst)
fst
获取双元素元组的第一个元素。
(==c)
是一个单参数函数,可将其输入与c
进行比较(有关更好的说明,请参阅http://www.haskell.org/tutorial/functions.html第3.2.1段)。