Functional Composition Hint

just looking for an explanation of how the following composition works:

(=<<) . return 

Where

 (=<<) :: (a -> mb) -> ma -> mb return :: a -> ma (.) :: (b -> c) -> (a -> b) -> a -> c 

End Type:

 GHCi> :t (=<<) . return (=<<) . return :: Monad m => mb -> ma -> mb 

I cannot understand how ma can be combined with (a โ†’ mb), i.e. how can we apply the return result, which is a simple type for the first argument (= <), expecting the type of the function?

+7
source share
2 answers

Explanation:

  • Your return (possibly unexpectedly) is a different monad than your =<< .
  • The monad he uses is the reader monad (->) r .

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

 return :: (mb) -> ((->) a (mb)) 

or in the usual infix notation

 return :: (mb) -> (a -> mb) 

See also:


Edit: To define a monad, we need a (partially applied) type of kind * -> * . These are almost always partially used data constructors, but in this particular case we consider -> as a type operator that takes 2 type arguments and creates a new type (function type). Therefore, for any given type r partially applied expression (->) r is a type of the form * -> * . As it turned out, there is a simple way to describe the operations of a monad on it. See Control.Reader monad, as well as this article that explains this. The monad operations for Reader are implemented in exactly the same way as for (->) , the only difference is that Reader transfers operations to a separate data type.

+7
source

I again, with the inscriptions, putting things side by side to help in visual understanding:

 g = ((=<<) . return) {- ((=<<) . return) xy === (=<<) (return x) y return :: a' -> m' a' (=<<) :: (a -> mb) -> ma -> mb return x :: m' a' , x :: a' m' a' m' ~ ((->) a) , a' ~ mb return x === const x -- instance Monad ((->) a) where return = const gxy === y >>= (\_ -> x) === y >> x (!!) -} g :: mb -> ma -> mb 

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

 Prelude> ((=<<).return) [1] "xyz" -- === (=<<) (const [1]) "xyz" -- === "xyz" >>= const [1] -- === "xyz" >> [1] -- === (>> [1]) "xyz" [1,1,1] 
+1
source

All Articles