2013-02-19 6 views
12

Ich denke, ich verstehe die Liste Monad aber dann fand ich, dass ich nicht bin. Hier ist die Geschichte.Soll (>>) die Ausgabe auf der linken Seite verwerfen?

Gegeben Liste m und Funktion k

> let m = [1..10] 
> :t m 
m :: [Integer] 

> let k = replicate 2 
> :t k 
k :: a -> [a] 

mit bind Spielen >>= geben, was ich

> :t (>>=) 
(>>=) :: Monad m => m a -> (a -> m b) -> m b 
> :t m >>= k 
m >>= k :: [Integer] 
> m >>= k 
[1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10] 

erwarten aber für >>

Erwartet (aus erleben mit IO Monade, alles auf links Seite würde verworfen werden)

m >> m 
[1,2,3,4,5,6,7,8,9,10] 

Got

> :t (>>) 
(>>) :: Monad m => m a -> m b -> m b 
:t m >> m 
m >> m :: [Integer] 
> m >> m 
[1,2,3,4,5,6,7,8,9,10,1,2,3,4,5 ... 9,10] -- truncated, real output is 100 elements 

Bitte erklären, warum >> ist nicht so verhalten, wie ich erwartet hatte (natürlich habe ich Mißverständnis muß) und was ist der richtige Weg >> zu interpretieren?

Antwort

25

(>>) verwirft Werte von seinem ersten Argument, aber nicht Effekte. In diesem Fall könnte es einfacher sein zu sehen, ob Sie eine Liste mit verschiedenen Arten verwenden:

λ> "ab" >> [1,2,3,4] 
[1,2,3,4,1,2,3,4] 

Hinweis, wie die Werte der ersten Liste überhaupt nicht verwendet.

Erinnern Sie sich an die Definition von (>>): a >> b = a >>= (\_ -> b). So wird dies "ab" >>= (\_ -> [1,2,3,4]), d.h. concat (map (\_ -> [1,2,3,4]) ['a','b']), d.h. concat [[1,2,3,4],[1,2,3,4]] (auch [i | _ <- "ab", i <- [1,2,3,4]]).

Mit [] bedeutet (>>=) so etwas wie "für jeden". Die Funktion auf der rechten Seite erhält als Argument jeden Wert auf der linken Seite. So (>>), die Werte verwirft, bedeutet immer noch "für jeden" - aber dieses Mal kann es den Wert nicht verwenden, also bedeutet es nur "die Elemente der zweiten Liste, die so oft wiederholt werden, wie es Elemente in der ersten Liste gibt ".

+0

Wow! Was für eine klare (und sehr schnelle) Antwort. Vielen Dank – wizzup

12

foo >> bar ist das gleiche wie foo >>= \_ -> bar. Im Fall von IO führt es die linke Aktion aus, ignoriert den Rückgabewert dieser Aktion und führt dann die richtige Aktion aus. Im Fall von Listen wird jedes Element in der linken Liste abgebildet, wobei der Wert der einzelnen Elemente ignoriert wird und die richtige Liste an jedem Punkt eingefügt wird.

Ein anderer Weg, um es zu betrachten ist, dass >>= für Listen ist die gleiche wie flip concatMap, >> die gleiche wie flip (concatMap . const) ist.

+0

Vielen Dank auch, zu schlecht, dass ich nur eine akzeptierte Antwort auswählen kann. – wizzup

Verwandte Themen