just looking for an explanation how does following composition work:
(=<<) . return
where
(=<<) :: (a -> m b) -> m a -> m b
return :: a -> m a
(.) :: (b -> c) -> (a -> b) -> a -> c
The final type:
GHCi> :t (=<<) . return
(=<<) . return :: Monad m => m b -> m a -> m b
I cann’t grasp how can match m a with (a -> m b) , ie. how can apply result of return which is a simple type to first argument of (=<<) expecting a function type ?
The explanation is:
returnis (perhaps unexpectedly) of a different monad than your=<<.(->) r.The compiler tries to unify the result of
return :: c -> m' cwith the first argument of(a -> m b) -> m a -> m b, so to unifym' cwitha -> m b. The only possibility is thatm'is the reader monad(->) rfor somer. Next, it tries to unify(->) r cwith (converted to the prefix notation)(->) a (m b), which is solved by settingrtoaandctom b. So, after unification, the compiler gets the most general possible typeor in the usual infix notation
See also:
Monad ((->) r)is defined.Edit: To define a monad, we need a (partially applied) type of kind
* -> *. These are almost always partially applied data constructors, but this particular case, we view->as a type operator that takes 2 type arguments and creates a new type (the function type). So for any given typer, the partially applied expression(->) ris a type of kind* -> *. As it turns out, there is a straightforward way how to describe monad operations on it. See Control.Reader monad and also this article that explains it. The monad operations forReaderare implemented exactly the same way as for(->), the only difference is thatReaderwraps the operations into a distinct data type.