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?
monads are used to address the more general problem of computations (involving state, input/output, backtracking, ...) returning values: they do not solve any input/output-problems directly but rather provide an elegant and flexible abstraction of many solutions to related problems.
Monad is a simple and powerful design pattern for function composition that helps us to solve very common IT problems such as input/output, exception handling, parsing, concurrency and other. Application becomes less error prone.
monad, (from Greek monas “unit”), an elementary individual substance that reflects the order of the world and from which material properties are derived. The term was first used by the Pythagoreans as the name of the beginning number of a series, from which all following numbers derived.
A monadic function is a function with a single argument, written to its right. It is one of three possible function valences; the other two are dyadic and niladic. The term prefix function is used outside of APL to describe APL's monadic function syntax.
You could ask the same question of any Monad
. Off the top of my head, I can think of three advantages:
Monad
s.do
-notation.This also allows you to reason better about your code, since you can rely on identity and associative properties and the like.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With