简体   繁体   中英

Bind operator for non-monadic functions

I more or less wrapped my head around monads, but i can't deduct how expression

(>>=) id (+) 3

evaluates to 6. It just seems the expression somehow got simplified to

(+) 3 3

but how? How is 3 applied twice? Could someone explain what is happening behind the scenes?

This follows from how >>= is defined for the ((->) r) types:

(f =<< g) x  =  f (g x) x

Thus

(>>=) id (+) 3
=
(id >>= (+)) 3
=
((+) =<< id) 3
=
(+) (id 3) 3
=
3 + 3

see the types:

> :t let (f =<< g) x = f (g x) x in (=<<)
let (f =<< g) x = f (g x) x in (=<<)
        :: (t1 -> (t2 -> t)) -> (t2 -> t1) -> (t2 -> t)

> :t (=<<)
(=<<) :: Monad m => (a -> m b) -> m a -> m b

The types match with

t1 ~ a
(t2 ->) ~ m    -- this is actually ((->) t2)`
t ~ b

Thus the constraint Monad m here means Monad ((->) t2) , and that defines the definition of =<< and >>= which get used.

If you want to deduce the definition from the type,

(>>=) :: Monad m => m a -> (a -> m b) -> m b
m ~ ((->) r)

(>>=) :: (r -> a) -> (a -> r -> b) -> (r -> b)
(>>=)    f            g                r =  b
  where
  a  = f r
  rb = g a
  b  = rb r

which after the simplification becomes the one we used above.

And if you want to understand it "with words",

(=<<) :: (Monad m, m ~ ((->) r)) => (a -> m b) -> m a -> m b
(f =<< g) x  =  f (g x) x
  • g is a "monadic value" that " can compute" an " a ", represented as r -> a
  • fa calculates a "monadic value" that " can compute" a " b ", represented as r -> b ,
  • thus \x -> f (gx) x is a monadic value that " can compute" a " b ", given an " r ".

Thus in your example, g = id , f = (+) , and

  • id is a "monadic value" that " can compute" an " a ", an a -> a
  • (+) a calculates a "monadic value" that " can compute" a " b ", an a -> b , which b is actually also an a ,
  • thus \x -> (+) (id x) x is a monadic value that " can compute" an " a ", given an " a ":
(>>=) id (+)
=
((+) =<< id) 
=
\x -> (+) (id x) x
=
\x -> (+)     x  x

Adding some colour to Will's excellent answer.

If we look at the source , we have this:

 instance Monad ((->) r) where f >>= k = \ r -> k (fr) r

If we rearrange the input expression slightly, we get (id >>= (+)) 3 . This now resembles the form shown above. Now fitting the input into the above 'template', we can rewrite the input as \ r -> (+) (id r) r

This is the same expression we arrived at for the final evaluation ie (+) (id 3) 3

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM