I have some confusion with the function monad. The function monad is defined as follow:
instance Monad ((->) r) where
return x = \_ -> x
h >>= f = \w -> f (h w) w
I tried to play around with it by writing a binding operation:
( (*2) >>= (+10) ) 3
(return 3) :: ((->) Int)
But it caused errors. And I also try to rewrite a function AddStuff into the binding operations.
addStuff = do
a <- (*2)
b <- (+10)
return (a+b)
then convert this function into
addStuff' w = (*2) w >>= (\a ->
(+10) w >>= (\b ->
return (a+b) ))
I check the type of the new function as see
addStuff :: (Monad m, Num (m b), Num b) => m b -> m b
Why is that? How can I fix that?
In
addStuff'you write(*2) wand(+10) w. Those are equivalent tow*2andw+10respectively. SoaddStuff'is equivalent to this:Writing it this way should make it obvious that here the left operands to
>>=are numbers, not functions. That’s why the inferred type is telling you that your function only works for numbers that are monads.When eliminating
donotation the left operand to>>=should be exactly the same as the right operand of<-. Also eliminatingdonotation does not add any arguments to the function. So the correct rewriting would look like this:As to why your earlier pieces of code don’t work:
The operator
>>=has typem a -> (a -> m b) -> m b. For simplicity let’s assume that all the numbers in this code have typeInt, then your left operand has typeInt -> Intorm Intifmis(->) Int. So for some typebthe right operand should have typeInt -> ((->) Int) bor, more readably,Int -> Int -> b. The type it actually has though isInt -> Int. Therefore your expression is ill-typed.((->) Int)has kind* -> *– the type of a value must have kind*.Or to approach this differently:
return 3has typem Intfor somem(still assuming that all integer literals have typeIntfor simplicity). So ifmis((->) Int), the type ofreturn 3will be((->) Int) IntorInt -> Int, not((->) Int).