[Haskell-cafe] Proposal: Subcomputations in arrow notation

Ertugrul Soeylemez es at ertes.de
Wed Sep 21 21:04:54 CEST 2011


Hello fellow Haskellers,

this is a proposal to extend the arrow notation (-XArrows).  I find
myself writing the following very often:

    system :: Wire IO () String
    system =
        proc _ -> do
            botAddPeriod <- succ ^<< noise -< ()
            botAddSpeed <- noise1 -< ()
            botAddStart <- noise1 -< ()
            botMsg <- event addBot -< (botAddPeriod, botAddSpeed, botAddStart)

            bots <- manager -< ((), maybe MgrNop id botMsg)
            let botStr = concatMap (printf "%8.2") . M.elems $ bots :: String
            identity -< printf "Bot positions: %s" botStr

        where
        addBot :: Wire IO (Double, Double, Double) (MgrMsg Int IO () Double)
        addBot =
            proc (addPeriod, addSpeed, addStart) -> do
                periodically -< addPeriod
                botId <- identifier -< ()
                identity -< MgrAdd botId (constant addSpeed >>> integral addStart)

The relevant part is the first paragraph of the first arrow computation:

    botAddPeriod <- succ ^<< noise -< ()
    botAddSpeed <- noise1 -< ()
    botAddStart <- noise1 -< ()
    botMsg <- event addBot -< (botAddPeriod, botAddSpeed, botAddStart)

This line should generate a message for the bot manager at random
intervals.  The actual event generator is in the second arrow
computation 'addBot'.  I would like to be able to write this more in
line with the rest of the code.  The following is possible:

    system :: Wire IO () String
    system =
        proc _ -> do
            botAddPeriod <- succ ^<< noise -< ()
            botAddSpeed <- noise1 -< ()
            botAddStart <- noise1 -< ()

            botMsg <- event (proc (addPeriod, addSpeed, addStart) -> do
                periodically -< addPeriod
                botId <- identifier -< ()
                identity -< MgrAdd botId (constant addSpeed >>> integral addStart))
                -< (botAddPeriod, botAddSpeed, botAddStart)

            bots <- manager -< ((), maybe MgrNop id botMsg)
            let botStr = concatMap (printf "%8.2") . M.elems $ bots :: String
            identity -< printf "Bot positions: %s" botStr

This is probably not a big improvement.  It's more concise, but also
harder to understand.  My proposal is to add syntax to allow the
following notation:

    system :: Wire IO () String
    system =
        proc _ -> do
            botAddPeriod <- succ ^<< noise -< ()
            botAddSpeed <- noise1 -< ()
            botAddStart <- noise1 -< ()

            botMsg <- event $ do
                periodically -< addPeriod
                botId <- identifier -< ()
                identity -< MgrAdd botId (constant addSpeed >>> integral addStart)

            bots <- manager -< ((), maybe MgrNop id botMsg)
            let botStr = concatMap (printf "%8.2") . M.elems $ bots :: String
            identity -< printf "Bot positions: %s" botStr

Again the relevant part is the event generator in the middle.  In this
hypothetical syntax, the compiler would figure out from the inner
computation, which variables from the outer scope are used and pass them
automatically in an appropriate tuple.  You wouldn't need any explicit
passing anymore.

If others like the idea, too, and there is nobody to implement it, then
I would be willing to get in touch with the GHC code and implement this
as a patch myself.

What do you think?


Greets,
Ertugrul


-- 
nightmare = unsafePerformIO (getWrongWife >>= sex)
http://ertes.de/





More information about the Haskell-Cafe mailing list