0

I have the following CPS implementation of until:

until' p f x cc = p x (\y -> if y then cc(x)
                             else until' p f (f x (\z -> cc(z))) cc)

Which type checks ok! Now, trying to CPS map:

map' f (x:xs) cc = f x (\y -> map f xs (\ys -> cc(y:ys)))

Another possible implementation:

map' f (x:xs) cc = cc(f x (\y cc' -> map f xs (\ys -> cc'(y:ys))))

However none of them type checks. Where am I doing the mistake?

    Couldn't match expected type ‘([a1] -> t2) -> t1’
                with actual type ‘[(a1 -> t1) -> t]’
    Relevant bindings include
      y :: a1 (bound at test.hs:6:26)
      cc :: [a1] -> t2 (bound at test.hs:6:15)
      f :: a -> (a1 -> t1) -> t (bound at test.hs:6:6)
      map' :: (a -> (a1 -> t1) -> t) -> [a] -> ([a1] -> t2) -> t
        (bound at test.hs:6:1)
    The function ‘map’ is applied to three arguments,
    but its type ‘(a -> (a1 -> t1) -> t) -> [a] -> [(a1 -> t1) -> t]’
    has only two
    In the expression: map f xs (\ ys -> cc (y : ys))
    In the second argument of ‘f’, namely
      ‘(\ y -> map f xs (\ ys -> cc (y : ys)))’
Failed, modules loaded: none.
cybertextron
  • 10,547
  • 28
  • 104
  • 208

2 Answers2

4

When rewriting in CPS the continuation takes the result, so if you write the expected type of your map function you have:

mapk :: (a -> b) -> [a] -> ([b] -> r) -> r

so the continuation takes the result list as a parameter. If you look at your implementation:

map' f (x:xs) cc = f x (\y -> map f xs (\ys -> cc(y:ys)))

y and ys should have the same type ([b]) however you are trying to combine them with (:) which expects a b and [b]. Instead you want something like:

mapk _ [] k = k []
mapk f (x:xs) k = mapk f xs (\rs -> k $ (f x):rs)
Lee
  • 142,018
  • 20
  • 234
  • 287
0

It was a typo on

map' f (x:xs) cc = f x (\y -> map f xs (\ys -> cc(y:ys)))

should be:

map' f (x:xs) cc = f x (\y -> map' f xs (\ys -> cc(y:ys)))
cybertextron
  • 10,547
  • 28
  • 104
  • 208