Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

proving monad laws

532 views
Skip to first unread message

andrea

unread,
Mar 31, 2008, 7:01:14 PM3/31/08
to
Given the three monad laws


(return x) >>= f == f x
m >>= return == m
(m >>= f) >>= g == m >>= (\x -> f x >>= g)

If I create a new monad, should I try to see if they are actually true??
how could you prove that for any f or m?

I was trying with the simple Maybe monad with some numerical examples,
but with no luck.

*Main Monad> let t = Just 10
*Main Monad> (return t) >>= (+1)

<interactive>:1:15:
No instance for (Num (Maybe Integer))
arising from a use of `+' at <interactive>:1:15-18
Possible fix: add an instance declaration for (Num (Maybe Integer))
In the second argument of `(>>=)', namely `(+ 1)'
In the expression: (return t) >>= (+ 1)
In the definition of `it': it = (return t) >>= (+ 1)

Shouldn't be the function be of type (Integer -> Integer)? Am I missing
something (as usual)?

Gareth McCaughan

unread,
Mar 31, 2008, 7:50:49 PM3/31/08
to
"andrea" wrote:

> Given the three monad laws
>
>
> (return x) >>= f == f x
> m >>= return == m
> (m >>= f) >>= g == m >>= (\x -> f x >>= g)
>
> If I create a new monad, should I try to see if they are actually true??
> how could you prove that for any f or m?
>
> I was trying with the simple Maybe monad with some numerical examples,
> but with no luck.
>
> *Main Monad> let t = Just 10
> *Main Monad> (return t) >>= (+1)

So you're trying to apply

(return x) >>= f == f x

in the case where

x == Just 10
f == (+1)

which means the RHS is

(+1) (Just 10)

or

(Just 10) + 1

which doesn't work because (Just 10) is of type Maybe Integer.
As the machine helpfully tells you:

> <interactive>:1:15:
> No instance for (Num (Maybe Integer))
> arising from a use of `+' at <interactive>:1:15-18
> Possible fix: add an instance declaration for (Num (Maybe Integer))
> In the second argument of `(>>=)', namely `(+ 1)'
> In the expression: (return t) >>= (+ 1)
> In the definition of `it': it = (return t) >>= (+ 1)

If instead you take x == 10 then you should get the right types.
(In the Maybe monad, return == Just.)

--
Gareth McCaughan
.sig under construc

Vesa Karvonen

unread,
Apr 1, 2008, 4:23:03 AM4/1/08
to
andrea <kern...@gmail.com> wrote:
> Given the three monad laws

> (return x) >>= f == f x
> m >>= return == m
> (m >>= f) >>= g == m >>= (\x -> f x >>= g)

> If I create a new monad, should I try to see if they are actually true??

Well, yes. To program without understanding is voodoo.

> how could you prove that for any f or m?

One way is to do a little calculation, using the definitions of the
combinators (return and >>=) and the rules of the language. You start
with the left hand side of a law and transform it step-by-step until you
reach the right hand side of the law.

As it happens, I've been recently tinkering with a monadic iterator
combinator library in Standard ML:

http://mlton.org/cgi-bin/viewsvn.cgi/*checkout*/mltonlib/trunk/com/ssh/extended-basis/unstable/public/control/iter.sig

An iterator, or enumerator, is a higher-order function that applies a
given function to elements drawn from a sequence of some kind:

type 'a t = ('a unit) -> unit

(Note: In Haskell one possible type for the iterator monad would be

newtype Monad m => Iter m a = Iter {for :: (a -> m ()) -> m ()} .)

It turns out that iterators can be augmented to a monad with plus:

fun return x = fn e => e x
fun aM >>= a2bM = fn e => aM (fn a => a2bM a e)
val zero = fn _ => ()
fun aM <|> bM = fn e => (aM e ; bM e)

The iterator monad is related to the continuation (or cps) monad (has
similar types and implementations of return and >>=) and the list monad
(the list monad and the iterator monad satisfy the same monad and monad
plus laws). To verify that the laws really hold, I did a little
calculation. Below are proof sketches for the monad plus laws of the
iterator monad.

Left Identity (Monoid): zero <|> m = m

zero <|> m (<|>)
fn e => (zero e ; m e) (zero)
fn e => (() ; m e) (nop)
fn e => m e (eta)
m

Right Identity (Monoid): m <|> zero = m

m <|> zero (<|>)
fn e => (m e ; zero e) (zero)
fn e => (m e ; ()) (nop)
fn e => m e (eta)
m

Assoc (Monoid): (x <|> y) <|> z = x <|> (y <|> z)

(x <|> y) <|> z (<|>)
fn e => ((x <|> y) e ; z e) (<|>)
fn e => ((fn e => (x e ; y e)) e ; z e) (beta)
fn e => ((x e ; y e) ; z e) (seq)
fn e => (x e ; (y e ; z e)) (beta)
fn e => (x e ; (fn e => (y e ; z e)) e) (<|>)
fn e => (x e ; (y <|> z) e) (<|>)
x <|> (y <|> z)

Left Zero: zero >>= f = zero

zero >>= f (>>=)
fn e => zero (fn a => f a e) (zero)
fn e => (fn _ => ()) (fn a => f a e) (beta)
fn e => () (zero)
zero

Left Distribution: (x <|> y) >>= f = (x >>= f) <|> (y >>= f)

(x <|> y) >>= f (>>=)
fn e => (x <|> y) (fn a => f a e) (<|>)
fn e => (fn e => (x e ; y e)) (fn a => f a e) (beta)
fn e => (x (fn a => f a e) ; y (fn a => f a e)) (beta * 2)
fn e => ((fn e => x (fn a => f a e)) e
; (fn e => y (fn a => f a e)) e) (>>= * 2)
fn e => ((x >>= f) e ; (y >>= f) e) (<|>)
(x >>= f) <|> (y >>= f)

-Vesa Karvonen

andrea

unread,
Apr 1, 2008, 4:23:26 AM4/1/08
to

Ok
return x == Just x
of course works, but it's not the monad law I think...
I know that the types were wrong, but I just tried to apply the law,
how can it be done then?
THanks

Gareth McCaughan

unread,
Apr 1, 2008, 5:03:25 AM4/1/08
to
"andrea" wrote:

[me:]


>> If instead you take x == 10 then you should get the right types.
>> (In the Maybe monad, return == Just.)

[Andrea:]


> return x == Just x
> of course works, but it's not the monad law I think...

Why do you think that, and what do you think *is* the
monad law?

See, e.g.,
http://en.wikipedia.org/wiki/Monads_in_functional_programming
http://www.haskell.org/all_about_monads/html/maybemonad.html
http://www.randomhacks.net/articles/2007/03/12/monads-in-15-minutes
which are the top three Google results for "maybe monad"
and all mention that the Maybe monad's return is Just.

> I know that the types were wrong, but I just tried to apply the law,
> how can it be done then?

I'm afraid I don't understand the question.

andrea

unread,
Apr 1, 2008, 7:45:00 AM4/1/08
to
On 1 Apr, 11:03, Gareth McCaughan <Gareth.McCaug...@pobox.com> wrote:
> "andrea" wrote:
>
> [me:]
>
> >> If instead you take x == 10 then you should get the right types.
> >> (In the Maybe monad, return == Just.)
>
> [Andrea:]
>
> > return x == Just x
> > of course works, but it's not the monad law I think...
>
> Why do you think that, and what do you think *is* the
> monad law?

Ok this
*Transform List> (return 10 >>= Just) == Just 10
True

Looks more like the "proof" of the law, doesn't it?

Vesa Karvonen

unread,
Apr 1, 2008, 8:29:31 AM4/1/08
to

No, your example is not a proof of the left identity law

return x >>= f = f x

for arbitrary x and f, which is what I assume you are trying to prove.

One problem with your example is that you use a specific f. Your example
would pass if one would define

return x = Just x
Nothing >>= _ = Nothing
Just x >>= _ = Just x

but the above definitions do not satisfy the left identity law, so your
example is not a sufficient condition to prove the left identity law for
the maybe monad.

The maybe monad is defined as:

return x = Just x
Nothing >>= _ = Nothing
Just x >>= f = f x

To prove the left identity law for the maybe monad, one simply needs to
observe that

return x >>= f (by definition of return)
= Just x >>= f (by definition of >>=)
= f x

which proves it.

-Vesa Karvonen

andrea

unread,
Apr 5, 2008, 3:26:00 PM4/5/08
to
On 1 Apr, 14:29, Vesa Karvonen <vesa.karvo...@cs.helsinki.fi> wrote:

Ok thanks a lot it was easy, just apply definitions and looks if it
matches...

0 new messages