[Haskell-cafe] What pattern is this (Something.T -> IO a) in Sound.ALSA.Sequencer

Roman Cheplyaka roma at ro-che.info
Tue Mar 5 14:33:05 CET 2013


* Martin Drautzburg <Martin.Drautzburg at web.de> [2013-03-04 21:21:30+0100]
> 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



More information about the Haskell-Cafe mailing list