2014-04-06 70 views
4

The very first 1-Haskell-a-Day的練習使我感到困惑不已。 目標是過濾出列表中的元素,除非它等於後面的元素。例如。這個函數中用於= <<的monad是什麼?

> filterByPair [1, 2, 2, 2, 3, 3, 4] 
[2,2,3] 

(我試圖讓兩個偏移列表,壓縮他們到的元組並刪除不具有相同數量的元組兩次,例如:[(2,2),(2,2), (3,3)]等) 但頭腦,blowingly簡單的解決方案使用=<<綁定運營商:

filterByPair :: Eq a => [a] -> [a] 
filterByPair = (init =<<) . group 

我無法搞清楚的是運營商的。當我嘗試使用它,我不明白在ghci中相同的結果:

> init =<< [2,3,4] 
No instance for (Num [b0]) arising from the literal `2' 

我發現,在ghci中,我可以使用,比如說,replicate=<<。這似乎列表中的每個元素被送入功能:

> replicate 2 =<< [2,3,4] 
[2,2,3,3,4,4] 

所以先復飛等同於:

> replicate 2 2 
[2,2] 

它在某種程度上知道擺在第二個參數列表replicate,不是第一個,並輸出他們都在一個大名單,而不是獨立的,如fmap作用:

> fmap (replicate 2) [2,3,4] 
[[2,2],[3,3],[4,4]] 

我讀過的結合operato r由正在使用的monad定義。這是一個monad函數,不是嗎?與filterByPair單元在哪裏?它是否與Eq類型類簽名有關?

同樣,如果我自己在ghci中使用=<<,那裏使用了什麼monad?

+1

'group'的類型爲'Eq a => [a] - > [[a]]''。也許'[2,3,4]'不太適合'[[a]]'這一事實與你所遇到的類型錯誤有關。如果你嘗試一些實際上是列表清單的東西呢? –

+1

這一個是在wiki上解釋的:https://github.com/1HaskellADay/1HAD/wiki/2014-02-24-filterByPair – Nicolas

回答

4

首先,filterPairs改寫成貼題形式清晰:

filterPairs xs = group xs >>= init 

我們就可以得到一個好主意,什麼單從類型發生。

xs :: Eq a => [a] 
group :: Eq a => [a] -> [[a]] 
init :: [a] -> [a] 

(>>=) :: Monad m => m a -> (a -> m b) -> m b 

的第一個參數是(>>=)group xs :: [[s]],所以如果我們在替換(>>=)m ~ []a ~ [s]我們會得到

(>>=) :: [[a]] -> ([a] -> [s]) -> [s] 

所以,我們正在使用的[]這裏Monad情況下,這相當於到concatMap(檢查類型!)。現在,我們可以,如果你弄清楚如何concatMapinitgroup工作,你應該能夠弄清楚如何原來filterPairs作品再次改寫filterPairs

filterPairs xs = concatMap init (group xs) 

現在。

+0

感謝您的支持。問題:你在列表monad中說,bind等價於concatMap。如何知道這一點?它在Hackage的任何地方都有記錄嗎? –

+0

請注意,當一元類型爲「List」時,'concatMap'只相當於'(= <<)'。 當使用concatMap(以及更一般的列表)時,如果嘗試使其更「通用」,您將需要替換'[]〜m'並回退綁定。 – smwhr