mix-arrows-0.1: Mixing effects of one arrow into another one



We try to mix effects of two completely unrelated arrows a and b, where b is considered pure, and a — impure. Probably the most common use case would be a = Kleisli IO. We perform all the pure calculations first, and do the impure ones later.

Usage example:

newtype Test input output = Test {runTest :: Mix (Kleisli IO) (Kleisli (State String)) input output}
    deriving (Category, Arrow, ArrowChoice, ArrowLoop)

runStateMorphism :: s -> Kleisli (State s) :~> (->)
runStateMorphism s al i_input = evalState (runKleisli al i_input) s
execTest :: Test input output -> input -> IO output
execTest t = runKleisli $ arrCancelUnitFst $ unMix $ alongMap (runStateMorphism "") $ runTest $ first t

rd = Test {runTest = liftImpure $ Kleisli $ const getLine}
wr = Test {runTest = liftImpure $ Kleisli putStrLn}
gt = Test {runTest = liftPure $ Kleisli $ const get}
pt = Test {runTest = liftPure $ Kleisli put}

test =
    proc () ->
        do line <- rd -< ()  -- effect from IO
           pt -< line        -- effect from State
           line' <- gt -< () -- effect from State
           wr -< line'       -- effect from IO



data Mix a b input output Source

Mix a b is an arrow incapsulating both a and b effects. It's functorial in b.


AlongMap (Mix a) 
(Arrow a, Arrow b) => Arrow (Mix a b) 
(Arrow a, ArrowChoice b) => ArrowChoice (Mix a b) 
(Arrow a, ArrowLoop b) => ArrowLoop (Mix a b) 
(Arrow a, Arrow b) => Category (Mix a b) 

liftImpure :: (ArrowChoice a, ArrowLoop a, Arrow b) => a :~> Mix a bSource

We can lift impure arrows

liftPure :: (Arrow a, Arrow b) => b :~> Mix a bSource

Pure arrows can be lifted too

unMix :: Arrow a => Mix a (->) :~> aSource

We need some way to extract the real computation from this Mix; fortunately, if we manage to reduce the pure arrow to a function (using alongMap), we can reduce the type Mix a (->) to a.

unMix' :: Arrow a => Mix a a :~> aSource

If, for some reason, the pure arrow is, in fact, as impure as the impure one, we still can extract the real computation.