Andreas
Andreas

Reputation: 692

Haskell: 'do [1,2,3]; ["hello"]' behavior clarification

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

Answers (2)

Will Ness
Will Ness

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

Joachim Breitner
Joachim Breitner

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

Related Questions