module Data.HMemDb.RefConverter
(PreRefConv(PreRefConv, rcFrom, rcTo), RefConv(RefConv)) where
import Control.Applicative (Applicative(pure, (<*>)))
import Control.Monad (liftM2)
import Data.HMemDb.Bin (Bin, TableRefs(TRNil, TRPair), binPair, binUnit)
import Data.HMemDb.MapTVar (MS)
data PreRefConv r input output =
PreRefConv {rcFrom :: input -> MS r, rcTo :: r -> MS output}
data RefConv input output where
RefConv :: Bin r -> TableRefs r -> PreRefConv r input output -> RefConv input output
(|*|) ::
PreRefConv r1 input (middle -> output)
-> PreRefConv r2 input middle
-> PreRefConv (r1, r2) input output
p1 |*| p2 = PreRefConv from to where
from input = liftM2 (,) (rcFrom p1 input) (rcFrom p2 input)
to (r1, r2) = liftM2 ($) (rcTo p1 r1) (rcTo p2 r2)
instance Functor (RefConv input) where fmap h r = pure h <*> r
instance Applicative (RefConv input) where
pure output =
RefConv binUnit TRNil $
PreRefConv {rcFrom = const $ return (), rcTo = \ ~() -> return output}
RefConv bf trf pf <*> RefConv bx trx px =
RefConv (binPair bf bx) (TRPair trf trx) (pf |*| px)