
* Martin Drautzburg
On Sunday, 3. March 2013 21:11:21 Roman Cheplyaka wrote:
Admittedly, programming with callbacks is not very pleasant. So we have an excellent alternative — the continuation monad transformer!
This nested code
something1 $ \x -> do something2 $ \y -> do something3 $ \z -> do
can be equivalently rewritten as this linear code
import Control.Monad.Cont
flip runContT return $ do x <- ContT something1 y <- ContT something2 z <- ContT something3 lift $ do ...
Mind-blowing. Thanks a lot. Before I dig into the continuation monad transformer, one more question (demonstrating my ignorance):
The initialization actually starts with
main = (do SndSeq.withDefault SndSeq.Block $ \h -> do Client.setName (h :: SndSeq.T SndSeq.DuplexMode) "Haskell-Melody" Port.withSimple h "out" (Port.caps [Port.capRead, Port.capSubsRead, Port.capWrite]) (Port.types [Port.typeMidiGeneric, Port.typeApplication]) $ \p -> do
So there are some plain actions like "Client.setName" and "Port.withSimple" before it gets to the next "do" block. How would I write this in ContT style?
You can use the "lift" function to lift actions from the underlying monad to the transformer. In your case it'd be something like flip runContT return $ do h <- ContT $ SndSeq.withDefault SndSeq.Block lift $ Client.setName (h :: SndSeq.T SndSeq.DuplexMode) "Haskell-Melody" p <- ContT $ Port.withSimple h "out" (Port.caps [Port.capRead, Port.capSubsRead, Port.capWrite]) (Port.types [Port.typeMidiGeneric, Port.typeApplication]) ... Roman