這些是我在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