这些是我在Haskell的第一次探索,所以请原谅我,如果它应该是明显的。撰写concat和map来获取concatMap:为什么f?
我一直在和哈斯克尔一起玩,使用我自己的列表类型(典型的缺点)筛选教程99 questions on HaskellWiki。我继续添加了“显而易见”的功能,并且尽力使它们尽可能简洁(尽可能使用免注释符号)
第12个问题是关于解码运行长度编码列表,那就是:
> decode [Multiple 5 'a', Single 'b', Multiple 2 'c']
"aaaaabcc"
我想过使用map
每个元素进行解码,然后concat
结果(感谢谷歌在此),终于记起我曾见过类似的东西在我的读数,这GHCI很快证实concatMap
:
> :t map
map :: (a -> b) -> [a] -> [b]
> :t concat
concat :: [[a]] -> [a]
> :t concatMap
concatMap :: (a -> [b]) -> [a] -> [b]
它看起来像这将是显而易见的重新实现concatMap
:
concatMap :: (a -> [b]) -> [a] -> [b]
concatMap = concat . map
除GHCI颇为抱怨:
List.hs:110:15:
Couldn't match expected type `[a] -> [b]'
with actual type `[a0]'
Expected type: [[a0]] -> [a] -> [b]
Actual type: [[a0]] -> [[a0]]
In the first argument of `(.)', namely `concat'
In the expression: concat . map
我想不出来,所以我抬起头,在网络上,和Prelude中引用的定义其实是:
concatMap f = concat . map f
我不太明白为什么这个f是必须的,因为它的类型显然是a -> [b]
按照签名规定...
那么为什么f
这里需要?
啊!说'''右边的函数应该期待一个单一的论证是否公平? (在咖喱之前,不是2个“地图”?)另外,是否有一些技巧以点自由风格写出来? – 2011-04-02 17:40:16
@Matthiew Haskell中的每个函数都接受一个参数。例如,'map'接受一个函数并返回一个'g = map f'函数,该函数接受一个列表并返回一个元素。另外,请记住一件重要的事情:功能应用程序绑定比任何运算符都更紧密,它可以帮助您理清事情的真相。我不知道如何免费写这个观点。 – adamax 2011-04-02 17:46:33
这绝对是一个奇怪的旅程,我正在着手:)'replicateList :: Int - > List a - > List a'(Problem 15,changed)可以写成point'free作为'replicateList = concatMap。复制'和两个参数传递,没有类型检查问题。 – 2011-04-02 17:53:21