From learn you a haskell: http://learnyouahaskell.com/for-a-few-monads-more
Monad instance for function is this:
instance Monad ((->) r) where
return x = \_ -> x
h >>= f = \w -> f (h w) w
I am having trouble understanding the output of the following:
import Control.Monad.Instances
addStuff :: Int -> Int
addStuff = do
a <- (*2)
b <- (+10)
return (a+b)
addStuff 3 returns 19. Book says 3 gets passed as parameters to both (*2) and (+10). How?
From h >>= f = \w -> f (h w) w , it seems like (h w) is getting bound to a or b.
So, why 6 is not being passed in (+10)?
My understanding of f here is that when (*2) is h, f is the last 2 lines of addStuff. When (+10) is h, f is the last line (in this case the return statement) of addStuff.
Let us first desugar the do block [Haskell'10 report]:
addStuff = do
a <- (*2)
b <- (+10)
return (a+b)
is equivalent to:
addStuff = (*2) >>= \a -> ((+10) >>= \b -> return (a + b))
The inner bind expression ((+10) >>= \b -> return (a + b)), can thus be converted, with the bind definition to:
\w -> (\b -> return (a + b)) ((+10) w) w
and if we substitute return with const, we thus obtain:
\w -> (const . (a+)) ((+10) w) w
We thus have a function that takes as input w, and then calls const . (a+) on (w+10) and w, so it will ignore the last w. Semantically it is equivalent to:
(a+) . (+10)
So now our addStuf is equivalent to:
addStuff = (*2) >>= \a -> ((a+) . (+10))
and if we now use the definition for the bind operator again, we see:
\w -> (\a -> ((a+) . (+10))) ((*2) w) w
or shorter:
\w -> (\a -> ((a+) . (+10))) (w*2) w
We can now substitue a with (w*2) and obtain:
\w -> ((w*2)+) . (+10)) w
So our addStuf is equivalent to:
addStuff w = (w*2) + (w+10)
or more simple:
addStuff w = 3*w + 10
Haskell do notation is syntactic sugar for a series of >>= bindings; in this case, for something like this:
addStuff = (*2) >>= (\a -> (+10) >>= (\b -> return (a + b)))
Passing the updated argument between the computation steps (which would thus be serving a role of a state) is the job of another monad, namely the State monad.
The function aka Reader monad is simpler than that, does less work:
-- (return x) w = x
-- (h >>= f) w = f (h w) w
(h >>= (\a -> g >>= (\b -> return (f a b)))) w
=
(\a -> g >>= (\b -> return (f a b))) (h w) w
=
(g >>= (\b -> return (f (h w) b))) w
=
(\b -> return (f (h w) b))) (g w) w
=
return (f (h w) (g w)) w
=
f (h w) (g w)
Thus the input argument w is passed unchanged into both (by extension, all) the computation steps. Or in the specific case you ask about,
liftM2 (+) ( *2) ( +10) w
=
(+) (w*2) (w+10)
liftM2 function is equivalent to the do block that you show,
liftM2 f h g =
do {
a <- h ;
b <- g ;
return (f a b) }
=
h >>= (\ a ->
g >>= (\ b -> return (f a b) ))
in any monad.
Related
I have learnt about Monoidal being an alternative way to represent Applicative not so long ago. There is an interesting question on Typeclassopedia:
(Tricky) Prove that given your implementations from the first exercise [pure and (<*>) written down using unit and (**) and the other way around], the usual Applicative laws and the Monoidal laws stated above are equivalent.
Here are these classes and laws:
-- A note from https://wiki.haskell.org/Typeclassopedia#Alternative_formulation:
-- In this and the following laws, ≅ refers to isomorphism rather than equality.
-- In particular we consider (x,()) ≅ x ≅ ((),x) and ((x,y),z) ≅ (x,(y,z)).
-- Monoidal.
class Functor f => Monoidal f where
unit :: f ()
(**) :: f a -> f b -> f (a,b)
-- unit ** v ≅ v - Left Identity.
-- u ** unit ≅ u - Right Identity.
-- u ** (v ** w) ≅ (u ** v) ** w - Associativity.
-- Applicative.
class Functor f => Applicative f where
pure :: a -> f a
infixl 4 <*>, ...
(<*>) :: f (a -> b) -> f a -> f b
...
-- pure id <*> v = v - Identity.
-- pure f <*> pure x = pure (f x) - Homomorphism.
-- u <*> pure y = pure ($ y) <*> u - Interchange.
-- u <*> (v <*> w) = pure (.) <*> u <*> v <*> w - Composition.
Writing down combinators using others is no big deal:
unit = pure ()
f ** g = (,) <$> f <*> g = liftA2 (,) f g
pure x = const x <$> unit
f <*> g = uncurry ($) <$> (f ** g)
Here is my understanding of why the laws are telling us the same thing:
u <*> pure y = pure ($ y) <*> u -- Interchange: Applicative law.
The first thing we shall notice is that ($ y) ≅ y (more formally: (y -> a) -> a ≅ y). Having that in mind, Interchange law simply tells us that (a, b) ≅ (b, a).
pure id <*> v = v -- Identity: Applicative law.
I reckon id to be something of a unit itself as it is the only inhabitant of type forall a. a -> a. Therefore, this law gives us the Left Identity:
unit ** v = v -- Left Identity: Monoidal law.
Now we can use that (a, b) ≅ (b, a) to write the Right Identity down:
u ** unit = u -- Right Identity: Monoidal law.
The Composition law:
u <*> (v <*> w) = pure (.) <*> u <*> v <*> w -- Composition: Applicative law.
I reckon this law to tell the same thing as Associativity for Monoidal:
u ** (v ** w) ≅ (u ** v) ** w
That is, (a, (b, c)) ≅ ((a, b), c). Applicative just adds a layer of application.
So, we have covered all of the Monoidal laws. I believe there is no need to do it the other way around as we are going to use the same isomorphisms. But one could have noticed something odd - we did not use the Homomorphism Applicative law:
pure f <*> pure x = pure (f x)
I tried understanding Homomorphism in terms of the Naturality free theorem for Monoidal:
fmap (g *** h) (u ** v) = fmap g u ** fmap h v
But it seems odd as Homomorphism does not deal with side-effects, yet Naturality works with them just fine.
So, I have 3 questions:
Is my reasoning right?
Where does Homomorphism stand in this picture?
How can we understand the Naturality free theorem in terms of Applicative?
Just dumping this here for now... wanted to discuss this but I already spent way to long implementing it: it's a Coq proof script that shows the equivalence in an absolutely waterproof way.
Require Import Coq.Program.Basics.
Require Import Coq.Init.Datatypes.
Require Import Coq.Init.Notations.
Notation "f ∘ g" := (compose f g).
Class Functor (F: Type -> Type) : Type :=
{ fmap : forall {x} {y}, (x->y) -> (F x->F y)
; fmap_id : forall x, #fmap x x id = id
; fmap_compose : forall {x} {y} {z} (f: y->z) (g: x->y)
, fmap (f∘g) = fmap f ∘ fmap g
}.
Lemma fmap_twice {F} `{Functor F} {x} {y} {z} (f: y->z) (g: x->y) (xs: F x)
: fmap (f∘g) xs = fmap f (fmap g xs).
Proof.
rewrite fmap_compose. now compute.
Qed.
Definition parallel {a} {b} {c} {d} (f: a->c) (g: b->d)
: (a*b) -> (c*d) := fun xy => match xy with
| (x,y) => (f x, g y)
end.
Notation "f *** g" := (parallel f g) (at level 40, left associativity).
Definition rassoc {a} {b} {c} : ((a*b)*c) -> (a*(b*c))
:= fun xyz => match xyz with | ((x,y),z) => (x,(y,z)) end.
Definition tt_ {a} (x:a) := (tt, x).
Definition _tt {a} (x:a) := (x, tt).
Class Monoidal F `{Functor F} : Type :=
{ funit : F unit
; fzip : forall {a} {b}, F a -> F b -> F (a*b)
; left_identity : forall {a} (v: F a)
, fzip funit v = fmap tt_ v
; right_identity : forall {a} (v: F a)
, fzip v funit = fmap _tt v
; associativity : forall {a} {b} {c} (u: F a) (v: F b) (w: F c)
, fzip u (fzip v w) = fmap rassoc (fzip (fzip u v) w)
; naturality : forall {a} {b} {c} {d}
(g: a->c) (h: b->d) (u: F a) (v: F b)
, fmap (g***h) (fzip u v) = fzip (fmap g u) (fmap h v)
}.
Notation "u ** v" := (fzip u v) (at level 40, left associativity).
Lemma naturalityL {F} `{Monoidal F} {a} {b} {c}
(f: a->c) (u: F a) (v: F b)
: fmap (f***id) (fzip u v) = fzip (fmap f u) v.
Proof.
assert (v = fmap id v) as ->. { now rewrite fmap_id. }
rewrite <- naturality.
assert (v = fmap id v) as <-. { now rewrite fmap_id. }
now trivial.
Qed.
Lemma naturalityR {F} `{Monoidal F} {a} {b} {c}
(f: b->c) (u: F a) (v: F b)
: fmap (id***f) (fzip u v) = fzip u (fmap f v).
Proof.
assert (u = fmap id u) as ->. { now rewrite fmap_id. }
rewrite <- naturality.
assert (u = fmap id u) as <-. { now rewrite fmap_id. }
now trivial.
Qed.
Definition to {a} {b} (y: a) (f: a->b) := f y.
Class Applicative F `{Functor F} : Type :=
{ pure : forall {a}, a -> F a
; app : forall {a} {b}, F (a->b) -> F a -> F b
; identity : forall {a} (v: F a)
, app (pure id) v = v
; homomorphism : forall {a} {b} (f: a->b) (x: a)
, app (pure f) (pure x) = pure (f x)
; interchange : forall {a} {b} (u: F (a->b)) (y: a)
, app u (pure y) = app (pure (to y)) u
; composition : forall {a} {b} {c}
(u: F (b->c)) (v: F (a->b)) (w: F a)
, app u (app v w) = app (app (app (pure compose) u) v) w
; appFtor : forall {a} {b} (g: a->b) (x: F a)
, fmap g x = app (pure g) x
}.
Notation "fs <*> xs" := (app fs xs) (at level 40, left associativity).
Require Import Coq.Program.Tactics.
Require Import Coq.Logic.FunctionalExtensionality.
Definition apl {a} {b} (fx: (a->b)*a)
:= match fx with |(f,x) => f x end.
Program Instance MonoidalIsApplicative {F} `{Monoidal F}
: Applicative F
:= { pure := fun {a} (x: a) => fmap (const x) funit
; app := fun {a} {b} (fs: F (a->b)) (xs: F a)
=> fmap apl (fzip fs xs) }.
Next Obligation. (* identity *)
rewrite <- naturalityL.
rewrite -> left_identity.
repeat (rewrite <- fmap_twice).
rewrite -> fmap_id.
now compute.
Qed.
Next Obligation. (* homomorphism *)
rewrite <- naturality.
rewrite -> left_identity.
repeat (rewrite <- fmap_twice).
now compute.
Qed.
Next Obligation. (* interchange *)
rewrite <- naturalityL.
rewrite <- naturalityR.
repeat (rewrite <- fmap_twice).
rewrite -> right_identity.
rewrite -> left_identity.
repeat (rewrite <- fmap_twice).
now compute.
Qed.
Next Obligation. (* composition *)
rewrite <- naturalityR.
rewrite -> associativity.
repeat (rewrite <- naturalityL).
rewrite -> left_identity.
repeat (rewrite <- naturalityL).
repeat (rewrite <- fmap_twice).
f_equal. (* This part is just about *)
unfold compose. (* convincing Coq that two *)
apply functional_extensionality. (* functions are equal, it *)
intro x. (* has nothing to do with *)
destruct x as ((btc, atb), a0). (* applicative or monoidal *)
now compute. (* functors, specifically. *)
Qed.
Next Obligation. (* appFtor *)
rewrite <- naturalityL.
rewrite -> left_identity.
repeat (rewrite <- fmap_twice).
now compute.
Qed.
Lemma fmapPure {F} `{Applicative F} {a} {b}
(f: a->b) (x: a) : fmap f (pure x: F a) = pure (f x).
Proof.
rewrite -> appFtor.
now apply homomorphism.
Qed.
Lemma fmapBracket {F} `{Applicative F} {a} {b} {c} {d}
(f: c->d) (g: a->b->c) (xs: F a) (ys: F b)
: fmap f (fmap g xs<*>ys) = fmap (fun x y => f (g x y)) xs <*> ys.
Proof.
repeat (rewrite -> appFtor).
rewrite -> composition.
rewrite -> homomorphism.
rewrite -> composition.
repeat (rewrite -> homomorphism).
now compute.
Qed.
Lemma fmap_both {F} `{Applicative F} {a} {b} {c} {d}
(f: a->c->d) (g: b->c) (xs: F a) (ys: F b)
: fmap f xs <*> fmap g ys = fmap (fun x y => f x (g y)) xs <*> ys.
Proof.
repeat (rewrite -> appFtor).
rewrite -> composition.
repeat (rewrite <- appFtor).
rewrite <- fmap_twice.
rewrite -> interchange.
rewrite -> appFtor.
rewrite -> composition.
repeat (rewrite -> homomorphism).
rewrite <- appFtor.
now compute.
Qed.
Definition tup {a} {b} (x:a) (y:b) : (a*b) := (x,y).
Program Instance ApplicativeIsMonoidal {F} `{Applicative F}
: Monoidal F
:= { funit := pure tt
; fzip := fun {a} {b} (u: F a) (v: F b)
=> fmap tup u <*> v }.
Next Obligation. (* left_identity *)
repeat (rewrite -> appFtor).
rewrite -> homomorphism.
now compute.
Qed.
Next Obligation. (* right_identity *)
repeat (rewrite -> appFtor).
rewrite -> interchange.
rewrite -> composition.
repeat (rewrite -> homomorphism).
now compute.
Qed.
Next Obligation. (* associativity *)
repeat (rewrite -> fmapBracket).
rewrite -> composition.
repeat (rewrite <- appFtor).
rewrite <- fmap_twice.
rewrite -> fmap_both.
now compute.
Qed.
Next Obligation. (* naturality *)
rewrite -> fmap_both.
rewrite <- fmap_twice.
rewrite -> fmapBracket.
now compute.
Qed.
Compiled with Coq 8.9.1.
We have
-- Monoidal.
class Functor f => Monoidal f where
unit :: f ()
(**) :: f a -> f b -> f (a,b)
-- unit ** v ≅ v - Left Identity.
-- u ** unit ≅ u - Right Identity.
-- u ** (v ** w) ≅ (u ** v) ** w - Associativity.
-- Applicative,
class Functor f => Applicative f where
pure :: a -> f a
infixl 4 <*>
(<*>) :: f (a -> b) -> f a -> f b
-- pure id <*> v = v - Identity.
-- pure f <*> pure x = pure (f x) - Homomorphism.
-- u <*> pure y = pure ($ y) <*> u - Interchange.
-- u <*> (v <*> w) = pure (.) <*> u <*> v <*> w - Composition.
Implementation 1. Applicative --> Monoidal
unit = pure ()
xs ** ys = pure (,) <*> xs <*> ys
Implementation 2. Monoidal --> Applicative
pure x = const x <$> unit
fs <*> xs = uncurry ($) <$> (fs ** xs)
Now prove Monoidal Laws given Applicative Laws and Implementation 1:
Left Identity. unit ** v ≅ v
unit ** v = pure () ** v
= pure (,) <*> pure () <*> v
= pure (\x -> (,) () x) <*> v
= pure (\x -> (() , x)) <*> v
= pure (() ,) <*> v
≅ pure id <*> v
= v
Right Identity. u ** unit ≅ u
u ** unit = u ** pure ()
= pure (,) <*> u <*> pure ()
= pure ($ ()) <*> (pure (,) <*> u) -- u <*> pure y = pure ($ y) <*> u
-- u <*> (v <*> w) = pure (.) <*> u <*> v <*> w
= pure (.) <*> pure ($ ()) <*> pure (,) <*> u
= pure ((.) ($ ())) <*> pure (,) <*> u
= pure ((.) ($ ()) (,)) <*> u
= pure (\x -> (.) ($ ()) (,) x) <*> u
= pure (\x -> ($ ()) ((,) x)) <*> u
= pure (\x -> (,) x ()) <*> u
= pure (\x -> (x , ())) <*> u
= pure (, ()) <*> u
≅ pure id <*> u
= u
Associativity. u ** (v ** w) ≅ (u ** v) ** w
u ** (v ** w) = ......
You should be able to continue this. I hope I didn't make any mistakes here, but if I did, correct them.
Following Will Ness's advice:
Here is what we get of Homomorphism (besides the laws spoken of about, I used the law specifying how Applicative should relate to Functor: fmap g x = pure g <*> x.)
pure f <*> pure x =
= uncurry ($) <$> ((,) <$> (pure f) <*> (pure x)) =
= (uncurry ($) .) <$> ((,) <$> (pure f)) <*> (pure x) =
= ((uncurry ($) .) . (,) <$> (pure f)) <*> (pure x) =
= (uncurry ($) . (,) f) <$> (pure x) =
= pure $ (uncurry ($) . (,) f) x =
= pure (f x)
So, I guess both Homorphism and fs <*> xs = uncurry ($) <$> (fs ** xs) enable us to perform application on the level of functors.
instance Monad ((->) r) where
return x = \_ -> x
h >>= f = \w -> f (h w) w
import Control.Monad.Instances
addStuff :: Int -> Int
addStuff = do
a <- (*2)
b <- (+10)
return (a+b)
I'm trying to understand this monad by unwiding the do notation, because I think the do notation hides what happens.
If I understood correctly, this is what happens:
(*2) >>= (\a -> (+10) >>= (\b -> return (a+b)))
Now, if we take the rule for >>=, we must understand (*2) as h and (\a -> (+10) >>= (\b -> return (a+b))) as f. Applying h to w is easy, let's just say it is 2w (I don't know if 2w is valid in haskell but just for reasoning lets keep it this way. Now we have to apply f to h w or 2w. Well, f simply returns (+10) >>= (\b -> return (a+b)) for an specific a, which is 2w in our case, so f (hw) is (+10) >>= (\b -> return (2w+b)). We must first get what happens to (+10) >>= (\b -> return (2w + b)) before finally applying it to w.
Now we reidentify (+10) >>= (\b -> return (2w + b)) with our rule, so h is +10 and f is (\b -> return (2w + b)). Let's first do h w. We get w + 10. Now we need to apply f to h w. We get (return (2w + w + 10)).
So (return (2w + w + 10)) is what we need to apply to w in the first >>= that we were tyring to uwind. But I'm totally lost and I don't know what happened.
Am I thinking in the rigth way? This is so confusing. Is there a better way to think of it?
You're forgetting that operator >>= doesn't return just f (h w) w, but rather \w -> f (h w) w. That is, it returns a function, not a number.
By substituting it incorrectly you lost the outermost parameter w, so it's no wonder it remains free in your final expression.
To do this correctly, you have to substitute function bodies for their calls completely, without dropping stuff.
If you substitute the outermost >>=, you will get:
(*2) >>= (\a -> ...)
==
\w -> (\a -> ...) (w*2) w
Then, if you substitute the innermost >>=, you get:
\a -> (+10) >>= (\b -> return (a+b))
==
\a -> \w1 -> (\b -> return (a+b)) (w1 + 10) w1
Note that I use w1 instead of w. This is to avoid name collisions later on when I combine the substitutions, because these two ws come from two different lambda abstractions, so they're different variables.
Finally, substitute the return:
return (a+b)
==
\_ -> a+b
Now insert this last substitution into the previous one:
\a -> (+10) >>= (\b -> return (a+b))
==
\a -> \w1 -> (\b -> return (a+b)) (w1 + 10) w1
==
\a -> \w1 -> (\b -> \_ -> a+b) (w1 + 10) w1
And finally insert this into the very first substitution:
(*2) >>= (\a -> ...)
==
\w -> (\a -> ...) (w*2) w
==
\w -> (\a -> \w1 -> (\b -> \_ -> a+b) (w1 + 10) w1) (w*2) w
And now that all substitutions are compete, we can reduce. Start with applying the innermost lambda \b -> ...:
\w -> (\a -> \w1 -> (\_ -> a+w1+10) w1) (w*2) w
Now apply the new innermost lambda \_ -> ...:
\w -> (\a -> \w1 -> a+w1+10) (w*2) w
Now apply \a -> ...:
\w -> (\w1 -> w*2+w1+10) w
And finally apply the only remaining lambda \w1 -> ...:
\w -> w*2+w+10
And voila! The whole function reduces to \w -> (w*2) + (w+10), completely as expected.
First, we write out the implicit argument in your definition explicitly,
addStuff :: Int -> Int
addStuff = do
a <- (*2)
b <- (+10)
return (a+b)
=
addStuff :: Int -> Int
addStuff x = ( do
a <- (*2)
b <- (+10)
return (a+b) ) x
=
....
Then, with
return x = const x
(f =<< h) w = f (h w) w -- (f =<< h) = (h >>= f)
it should be easier to follow and substitute the definitions, line for line:
....
=
( (*2) >>= (\a -> -- (h >>= f) =
(+10) >>= (\b ->
const (a+b) ) ) ) x
=
( (\a -> -- = (f =<< h)
(+10) >>= (\b ->
const (a+b) ) ) =<< (*2) ) x -- (f =<< h) w =
=
(\a ->
(+10) >>= (\b ->
const (a+b) ) ) ( (*2) x) x -- = f (h w) w
=
( let a = (*2) x in -- parameter binding
(+10) >>= (\b ->
const (a+b) ) ) x
=
let a = (*2) x in -- float the let
((\b ->
const (a+b) ) =<< (+10) ) x -- swap the >>=
=
let a = (*2) x in
(\b -> -- (f =<< h) w =
const (a+b) ) ( (+10) x) x -- = f (h w) w
=
let a = (*2) x in
(let b = (+10) x in -- application
const (a+b) ) x
=
let a = (*2) x in -- do a <- (*2)
let b = (+10) x in -- b <- (+10)
const (a+b) x -- return (a+b)
The essence of reader monad is application to same argument shared between all calls.
Intuitively, each function call on the right-hand side of the <- is given an additional argument, which you can think of as the argument to addStuff itself.
Take
addStuff :: Int -> Int
addStuff = do
a <- (*2)
b <- (+10)
return (a+b)
and turn it into
addStuff :: Int -> Int
addStuff x = let a = (*2) x
b = (+10) x
in (a+b)
It looks a little less "strange" if you use the MonadReader instance for (->) r, which provides ask as a way to get direct access to the implicit value.
import Control.Monad.Reader
addStuff :: Int -> Int
addStuff = do
x <- ask -- ask is literally just id in this case
let a = x * 2
let b = x + 10
return (a + b)
I can compose pure functions:
let f x = x + 1
let g x = x + 2
let z = f . g
z 1 == 4
I seem to be able to compose monadic functions also:
let f x = Just (x + 1)
let g x = Just (x + 2)
let z x = f x >>= g
z 1 == Just 4
I think I should be able to treat f and g from the last example as applicatives and compose those also, just not sure how:
let f x = Just (x + 1)
let g x = Just (x + 2)
let z x = f <*> g -- this doesn't work
z 1 == Just 4
Is this doable?
Bonus points, can z x = f x >>= g be written as a point-free function? Something like z = f >>= g?
{-# LANGUAGE TypeOperators #-}
The (type-level) composition of any two applicative functors,
newtype (f :. g) a = Compose { getCompose :: f (g a)) }
is an applicative functor.
instance (Functor f, Functor g) => Functor (f :. g) where
fmap f = Compose . fmap (fmap f) . getCompose
instance (Applicative f, Applicative g) => Applicative (f :. g) where
pure = Compose . pure . pure
Compose fgf <*> Compose fgx = Compose ((<*>) <$> fgf <*> fgx)
Your example is the composition of the Maybe applicative with the "function" or "reader" applicative (->) r.
type ReaderWithMaybe r = ((->) r) :. Maybe
x, y :: ReaderWithMaybe Int Int
x = Compose $ \x -> Just (x + 1)
y = Compose $ \x -> Just (x + 2)
Since ReaderWithMaybe r is an Applicative you can do all the usual Applicative stuff. Here I'm smashing my two values together with +.
ghci> let z = (+) <$> x <*> y
ghci> getCompose z 3
Just 9 -- (3 + 1) + (3 + 2) == 9
Note that x and y both get the same input 3. That's the behaviour of (->) r's Applicative instance. If you want to take the result of f x = Just (x + 1) and feed it into g x = Just (x + 2) (to get something equivalent to h x = Just (x + 3)), well, that's what Monad is for.
Bonus points, can z x = f x >>= g be written as a point-free function? Something like z = f >>= g?
You can easily define Kleisli composition by hand.
(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c
f >=> g = \x -> f x >>= g
It happens that >=> already exists in the standard library, along with its sister <=<. They are lovingly known as the "fish" operators, and they live in Control.Monad.
Applicative functions aren't
let f x = Just $ x + 1
let g x = Just $ x + 2
, they're
let f = Just $ \x -> x + 1
let g = Just $ \x -> x + 2
. Composition then works like liftA2 (.) f g or (.) <$> f <*> g.
Maybe you will be interested by Kleisli composition of monads:
(<=<) :: Monad m => (b -> m c) -> (a -> m b) -> a -> m c
(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c
say ,
f :: a -> b
g :: b -> c
h :: c -> d
why the equation
h.(g.f) = (h.g).f
is right?
how to prove it?
and the composition operation is just a basic operation in Haskell,
or we can get one by ourselves? if so how to achieve it?
You can define the composition operator yourself as follows:
(.) :: (b -> c) -> (a -> b) -> a -> c
g . f = \x -> g (f x)
Now, to prove associativity:
lhs = h . (g . f)
= \x -> h ((g . f) x) -- substitution
= \x -> h ((\y -> g (f y)) x) -- substitution
= \x -> h (g (f x)) -- beta reduction
rhs = (h . g) . f
= \x -> (h . g) (f x) -- substitution
= \x -> (\y -> h (g y)) (f x) -- substitution
= \x -> h (g (f x)) -- beta reduction
Now, we have lhs = rhs. QED.
On the page http://en.wikibooks.org/wiki/Haskell/do_Notation, there's a very handy way to transform the do syntax with binding to the functional form (I mean, using >>=). It works well for quite a few case, until I encountered a piece of code involving functions as monad ((->) r)
The code is
addStuff :: Int -> Int
addStuff = do
a <- (*2)
b <- (+10)
return (a+b)
this is equivalent as define
addStuff = \x -> x*2+(x+10)
Now if I use the handy way to rewrite the do part, I get
addStuff = (*2) >>= \a ->
(+10) >>= \b ->
a + b
which gives a compiling error. I understand that a, b are Int (or other types of Num), so the last function (\b -> a + b) has type Int -> Int, instead of Int -> Int -> Int.
But does this mean there's not always a way to transform from do to >>= ? Is there any fix to this? Or I'm just using the rule incorrectly?
Problem to make the last monadic:
addStuff = (*2) >>= \a ->
(+10) >>= \b ->
return (a + b)
(you've already been answered, that) The correct expression must use return on the last line:
addStuff = (*2) >>= \a ->
(+10) >>= \b ->
return (a + b)
(expounding on that, for some clarification) i.e. return is part of a monad definition, not of do notation.
Substituting the actual definitions for ((->) r) monad, it is equivalent to
addStuff x
= ((\a -> (\b -> return (a + b)) =<< (+10) ) =<< (*2) ) x
= (\a -> (\b -> return (a + b)) =<< (+10) ) (x*2) x
= ( (\b -> return ((x*2) + b)) =<< (+10) ) x
= (\b -> return ((x*2) + b)) (x+10) x
= return ((x*2) + (x+10)) x
= const ((x*2) + (x+10)) x
= (x*2) + (x+10)
as expected. So in general, for functions,
do { a <- f ; b <- g ; ... ; n <- h ; return r a b ... n }
is the same as
\ x -> let a = f x in let b = g x in ... let n = h x in r a b ... n
(except that each identifier a,b,...,n shouldn't appear in the corresponding function call, because let bindings are recursive, and do bindings aren't).
The above do code is also exactly how liftM2 is defined in Control.Monad:
> liftM2 (+) (*2) (+10) 100
310
liftM_N for any N can be coded with the use of liftM and ap:
> (\a b c -> a+b+c) `liftM` (*2) `ap` (+10) `ap` (+1000) $ 100
1410
liftM is the monadic equivalent of fmap, which for functions is (.), so
(+) `liftM` (*2) `ap` (+10) $ x
= (+) . (*2) `ap` (+10) $ x
= ((+) . (*2)) x ( (+10) x )
= (x*2) + (x+10)
because ap f g x = f x (g x) for functions (a.k.a. S-combinator).