Question

I've been trying to learn CPS, seems I didn't really get my head around it, could you implement basic filter and map using Cont monad?

Was it helpful?

Solution

To do this, let's first start without the monad since CPS isn't dependent on it.

cpsMap :: (a -> b) -> [a] -> ([b] -> r) -> r
cpsMap f (a:as) c = cpsMap f as (c.(f a:))
cpsMap  _ []    c = c []

map' f xs = cpsMap f xs id

And now the Cont monad is trivial

contMap :: (a -> b) -> [a] ->  Cont r [b]
contMap f (a:as) = contMap f as >>= return . (f a :)
contMap _ [] = return []

map'' f xs = runCont (contMap f xs) id

The only difference here is we don't have to touch the continuations ourselves, return pipes the value into it for us.

To visualize it let's trace it with map'' (+1) [1..3]

as      | c
[1,2,3] | id
[2,3]   | id . (2 :)
[3]     | id . (2 :) . (3 :)
[]      | id . (2 :) . (3 :) . (4 :)
id . (2 :) . (3 :) . (4 :) $ []
[2, 3, 4]

Notice that all Cont does is wrap the ([b] -> r) -> r part of our code under a newtype. Really we can think of Cont as

newtype Cont r a = Cont ((a -> r) -> r)

I'll leave implementing filter to you :)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top