What good is the monad instance of Cont?
Asked Answered
S

2

8

I'm playing around with CPS and Control.Monad.Cont and wonder what we gain by noticing the monadic structure. For code like this:

sumOfSquares'cps :: Cont r Int -> Cont r Int -> Cont r Int
sumOfSquares'cps x y = x >>= \x' ->
                       y >>= \y' ->
                       return (x'*x' + y'*y')

Can easily be rewritten as

type Cont' r a = (a -> r) -> r

sos'cps :: Cont' r Int -> Cont' r Int -> Cont' r Int
sos'cps x y = \k -> x $ \x' -> 
                    y $ \y' -> 
                    k (x'*x' + y'*y') 

Don't get me wrong, but I can't see the sensation here apart from being able to use do notation and a newtype. I don't think that callCC is dependent on the monad instance either.

I'm lacking imagination to come up with an example. What do we actually get for declaring Cont r a monad?

Syndactyl answered 10/6, 2014 at 18:2 Comment(3)
"I don't think that callCC is dependent on the monad instance either". Strictly speaking, nothing ever is. For example, in the Maybe monad return = Just and (=<<) = maybe Nothing. The Monad class abstracts over preexisting functionality to make the things Michael Snoyman mentions in his answer possible.Bayern
Makes sense, after thinking about it. Although normally when I see refactored functions using bind, I get a cozy warm feeling in my stomach that tells me I did the right thing. I don't get it for Cont, because there is no real difference in syntax, I guess.Syndactyl
To understand why the syntactic sugar seems so particularly thin for Cont, you might want to check out The Mother of all Monads.Shaker
L
10

You could ask the same question of any Monad. Off the top of my head, I can think of three advantages:

  1. You get access to the huge collection of functions that are designed to work with Monads.
  2. You can use do-notation.
  3. You can stack up monad transformers to create something more powerful.

This also allows you to reason better about your code, since you can rely on identity and associative properties and the like.

Lalla answered 10/6, 2014 at 18:24 Comment(1)
Those are the things that popped into my head right after posting the question :). I guess I was disappointed by the nearly identical syntax where the bind operators in another monads make the code kind of neat. That's naive, because monads serve a different purpose than enhancing syntax.Syndactyl
I
6

One obvious advantage is that you can use the combinators defined for Monads (and Functors). For example, your function could be written using liftM2:

sumOfSquares'cps :: Cont r Int -> Cont r Int -> Cont r Int
sumOfSquares'cps = liftM2 sumSquares
  where sumSquares x y = x * x + y * y

this function does not rely on the monad being Cont and could be written with a more general type e.g.

sumOfSquaresM :: Monad m => m Int -> m Int -> m Int
Inhabit answered 10/6, 2014 at 18:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.