Control.Arrow.Mix
Description
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
Documentation
data Mix a b input output Source
Mix a b is an arrow incapsulating both a and b effects. It's functorial in b.
liftImpure :: (ArrowChoice a, ArrowLoop a, Arrow b) => a :~> Mix a bSource
We can lift impure arrows