这是我对 Haskell 的第一次探索,如果它很明显,请原谅我。
我整个下午都在玩 Haskell,仔细浏览教程HaskellWiki 上的 99 个问题 http://www.haskell.org/haskellwiki/99_questions,使用我自己的列表类型(典型的缺点)。我在继续时添加了“明显”的函数,并且尝试使它们尽可能简洁(尽可能使用无点表示法)
第12个问题是关于对游程编码列表进行解码的问题,即:
> decode [Multiple 5 'a', Single 'b', Multiple 2 'c']
"aaaaabcc"
我考虑过使用map
解码每个元素,然后concat
结果(感谢谷歌),最后想起我见过类似的东西concatMap
在我的阅读中,GHCi 很快证实了这一点:
> :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
这里有必要吗?