質問

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:

  1. Your return is (perhaps unexpectedly) of a different monad than your =<<.
  2. The monad it uses is the reader monad (->) r.

The compiler tries to unify the result of return :: c -> m' c with the first argument of (a -> m b) -> m a -> m b, so to unify m' c with a -> m b. The only possibility is that m' is the reader monad (->) r for some r. Next, it tries to unify (->) r c with (converted to the prefix notation) (->) a (m b), which is solved by setting r to a and c to m b. So, after unification, the compiler gets the most general possible type

return :: (m b) -> ((->) a (m b))

or in the usual infix notation

return :: (m b) -> (a -> m b)

See also:


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 type r, the partially applied expression (->) r is 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 for Reader are implemented exactly the same way as for (->), the only difference is that Reader wraps the operations into a distinct data type.

他のヒント

Me again, with the scribblings, putting stuff side-by-side to aid in visual comprehension:

g = ((=<<) . return)   {-

((=<<) . return) x y 
         ===   (=<<)    (return x)    y               return :: a' -> m' a'
               (=<<) :: (a -> m b) -> m a -> m b      return x :: m' a' , x :: a'
                          m'  a'                      m' ~ ((->) a) , a' ~ m b 

return x === const x             -- instance Monad ((->) a) where return = const
g x y === y >>= (\_ -> x) === y >> x   (!!)
-}

g :: m b -> m a -> m b

So as it turns out (and was perhaps apparent from the type signature), g === flip (>>):

Prelude> ((=<<).return) [1] "xyz"   -- ===  (=<<) (const [1]) "xyz" 
                                    -- ===  "xyz" >>= const [1]
                                    -- ===  "xyz" >> [1]
                                    -- ===  (>> [1]) "xyz"
[1,1,1]
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top