ANN: contstuff: CPS-based monad transformers

Hello fellow Haskellers, (after failing (again) to send to the haskell list, I'm posting this here. I've contacted the mailing list owner about this.) I'm announcing the 0.4.0 release of the 'contstuff' monad transformer library, an alternative to libraries like 'mtl', 'transformers' and 'monadLib': http://hackage.haskell.org/package/contstuff The difference is that contstuff makes heavy use of continuation passing style both to increase performance and to make certain control flow patterns more accessible, including abortion, accumulation of multiple results, etc. On the wiki there is a quickstart introduction to those of you, who are familiar with monad transformers in general: http://haskell.org/haskellwiki/Contstuff Feedback, positive as well as negative, is highly appreciated. Thank you. Greets, Ertugrul -- nightmare = unsafePerformIO (getWrongWife >>= sex) http://ertes.de/

Very interesting! And the API seems very nice, although I haven't used the package. Are there benchmarks for monad transformers? How big is the difference between CPS and non-CPS monad libraries? Cheers! -- Felipe.

Felipe Lessa
Very interesting! And the API seems very nice, although I haven't used the package.
Are there benchmarks for monad transformers? How big is the difference between CPS and non-CPS monad libraries?
I have run some small and probably not that meaningful benchmarks. For StateT it doesn't seem to make a lot of difference. ChoiceT appears to be considerably faster than [] in all tests I've made. As a small benchmark consider the following factoring functions, which return a (very redundant) list of factors of the argument: testComp1 :: Integral a => a -> [a] testComp1 n = do x <- [1..n] y <- [x+1..n] guard $ n - x /= y guard $ mod (x^2 - y^2) n == 0 return $ gcd n (x-y) testComp2 :: Integral a => a -> ChoiceT r i m a testComp2 n = do x <- choice [1..n] y <- choice [x+1..n] guard $ n - x /= y guard $ mod (x^2 - y^2) n == 0 return $ gcd n (x-y) On my machine testComp1 takes 5.6 seconds to finish, and testComp2 takes 3.9 seconds. The programs I've used to test are: main1, main2 :: IO () main1 = do hSetBuffering stdout (BlockBuffering Nothing) getArgs >>= mapM_ (print . testComp1 . read) main2 = do hSetBuffering stdout (BlockBuffering Nothing) getArgs >>= mapM_ (print . listChoice . testComp2 . read) To take this further I modified the benchmark to print only the first result found. To return a factor of 1237*65537 testComp1 needs 10.2 seconds, while testComp2 needs only 5.1 seconds. Here is the modified code (testComp1 and testComp2 remain unchanged): main1, main2 :: IO () main1 = getArgs >>= mapM_ (print . head . testComp1 . read) main2 = getArgs >>= mapM_ (print . maybeChoice . testComp2 . read) At least ChoiceT is faster than using regular lists, and it's also a CPS-based monad transformer, so you get all the goodies of CPS and combining monads: testComp3 :: (Integral a, Monad m, LiftBase m, Base m ~ IO) => a -> ChoiceT r i m a testComp3 n = do x <- choice [1..n] y <- choice [x+1..n] guard $ n - x /= y guard $ mod (x^2 - y^2) n == 0 let factor = gcd n (x-y) io $ printf "Factor found: %i\n" (toInteger factor) return factor Note that instead of 'listA' I'm using the 'choice' function, which is slightly faster, but even with 'listA' ChoiceT outperforms regular lists. Greets, Ertugrul -- nightmare = unsafePerformIO (getWrongWife >>= sex) http://ertes.de/
participants (2)
-
Ertugrul Soeylemez
-
Felipe Lessa