Search code examples
haskellfunctional-programmingmonadsdo-notation

What is the type of the variable in do-notation here in Haskell?


The codes below looks quite clear:

do 
  x <- Just 3
  y <- Just "!"
  Just (show x ++ y)

Here the type of x is Num and y is String. (<- here is used to take actual value out of the Monad)

However, this snippet looks not so clear to me:

import Control.Monad.Instances
addStuff :: Int -> Int
addStuff = do
  a <- (* 2)
  b <- (+ 10)
  return (a + b)

What is the type of a and type of b here? It seems they act like a Num, but a <- (* 2) and b <- (+ 10) looks cryptic here...

Does anyone have ideas about this?


Solution

  • Well, you've stumbled upon a kind of weird monad.

    The monad in question is the Monad ((->) r). Now, what does that mean? Well, it's the monad of functions of the form r -> *. I.e., of functions that take the same type of input.

    You asked what the type of a and b are in this instance. Well, they are both Num a => a, but that doesn't really explain much.

    Intuitively, we can understand the monad like this: A monadic value is a function that takes a value of type r as input. Whenever we bind in the monad, we take that value and pass it to the bound function.

    I.e., in our addStuff example, if we call addStuff 5, then a is bound to (*2) 5 (which is 10), and b is bound to (+10) 5 (which is 15).

    Let's see a simpler example from this monad to try to understand how it works precisely:

    mutate = do a <- (*2)
                return (a + 5)
    

    If we desugar this to a bind, we get:

    mutate = (*2) >>= (\a -> return (a + 5))
    

    Now, this doesn't help much, so let's use the definition of bind for this monad:

    mutate = \ r -> (\a -> return (a + 5)) ((*2) r) r
    

    This reduces to

    mutate = \ r -> return ((r*2) + 5) r
    

    Which we using the definition that return is const, can reduce to

    mutate = \ r -> (r*2) + 5
    

    Which is a function, that multiplies a number by 2, and then adds 5.

    That's one weird monad.