Reputation: 692
So I'm trying to understand exactly how the Haskell do
notation works.
I understand that it is used together with monads and that it basically expands (since it's actually syntactic sugar) into anonymous functions connected with either bind (>>=
) or then (>>
) as shown here https://en.wikibooks.org/wiki/Haskell/Syntactic_sugar#Do_notation.
However my question is why the following command
Prelude> do [1, 2, 3]; "hello"
returns
"hellohellohello"
I know that arrays are actually monads (and that strings are arrays of chars) but I fail to see how this results in the behavior above.
Upvotes: 3
Views: 171
Reputation: 71099
To complement Joachim Breitner's answer, here's a look at this from another angle:
do [1, 2, 3]
"hello"
is
do a <- [1, 2, 3]
b <- "hello"
return b
is
do a <- [1, 2, 3]
do b <- "hello"
do return b
is
[b | a <- [1,2,3], b <- "hello"]
is the same as the pseudocode
for a in (a list of Nums) [1, 2, 3]:
-- here we have `a` (a Num)
for b in (a list of Chars) "hello":
-- here we have that same `a` (a Num),
-- and `b` (which is a Char)
emit b -- whatever "emit" means
Of course, list comprehensions for lists (not "arrays") of stuff (whatever that stuff is, say Nums, Chars, etc.) desugar into the same concatMap
‐using code; but it is sometimes easier to handle them mentally, either as is, or as a specification for some nested loops.
In fact it seems that do
-notation could as easily have been a for
-notation in the first place.
Upvotes: 3
Reputation: 25782
do [1, 2, 3]; "hello"
desugars to
[1, 2, 3] >> "hello"
which is the same as
[1, 2, 3] >>= (\_ -> "hello")
which is the same as
concatMap (\_ -> "hello") [1, 2, 3]
which is the same as
concat (map (\_ -> "hello") [1, 2, 3])
which is the same as
concat [(\_ -> "hello") 1, (\_ -> "hello") 2, (\_ -> "hello") 3])
which is the same as
concat ["hello","hello","hello"]
which is the same as
"hellohellohello"
Upvotes: 18