Home > Software engineering >  Does Haskell's 'do' notation always involve a monad?
Does Haskell's 'do' notation always involve a monad?

Time:07-07

I had always figured that Haskell's do-notation was just sugar for monad composition (>>=). Then I came across this instance of it, and am not sure what monad is in use here, or whether there even is one:

rollDieThreeTimes :: (Die, Die, Die)
rollDieThreeTimes = do
  let s = mkStdGen 0
      (d1, s1) = randomR (1, 6) s
      (d2, s2) = randomR (1, 6) s1
      (d3, _) = randomR (1, 6) s2
  (intToDie d1, intToDie d2, intToDie d3)

intToDie :: Int -> Die
...

My questions:

  • Is there even a monad underlying the do-notation of this example?
  • If not, is there some special form of do-notation that permits this format of let-statements with no monad?
  • If there is a monad, which is it? And, how would one convert this do-notation into >>= form?

CodePudding user response:

do should always be used in a monadic context. But if you only have one expression in the do-block, then it desugars to just that expression, so there are no references to >>=, and no Monad constraint arises.

So you can write

do let x = a
       y = b
   foo

which is equivalent to

let x = a
    y = b
in foo

but really, you should just write the latter.

I haven't read HPFFP, which Google tells me is probably the book you got this example from. It comes from the chapter on State, and it seems like the author(s) introduce this as a simple state-less example, then later add state to it. Perhaps they chose this unusual construction for pedagogical reasons, for example to keep it similar to a later version using monadic binds in place of the let bindings.

  • Related