
wren ng thornton wrote:
Here's one big difference:
newtype ErrCPS e m a = ErrCPS { runErrCPS :: forall r . (e -> m r) -- error handler -> (a -> m r) -- success handler -> m r }
The analogous version I use is:
newtype MaybeCPS a = MaybeCPS (forall r. (a -> Maybe r) -> Maybe r)
While I also offer a transformer version of MaybeCPS, the transformer *does* suffer from significant slowdown. Also, for MaybeCPS it's better to leave the handlers inline in client code rather than to abstract them out; that helps to keep things concrete. So perhaps you should first try a direct CPS translation:
newtype ErrCPS e a = ErrCPS (forall r. (a -> Either e r) -> Either e r)
runErrCPS :: ErrCPS e a -> Either e a runErrCPS (ErrCPS f) = f return
I'd be curious if this version suffers the same slowdown.
With this change [1] I can't notice any difference for your benchmark[2]. Then again, all the runTest calls take 0 msec and I've had no luck making the computation take much time; perhaps your computer can detect a difference. You may want to see what standard benchmarking tools like Microbench[3] or the magnificent Criterion[4] have to say. I'd do it myself, but I haven't had a chance to reinstall everything since getting my new computer (due to the installation issues on newer versions of OSX). [1] http://community.haskell.org/~wren/wren-extras/src/Control/Monad/ErrCPS.hs [2] http://community.haskell.org/~wren/wren-extras/test/Control/Monad/ErrCPS/Max... [3] http://hackage.haskell.org/package/microbench [4] http://hackage.haskell.org/package/criterion -- Live well, ~wren