{-# LANGUAGE DeriveFunctor #-} {- | Module : Data.Transaction Copyright : Kadzuya Okamoto 2018 License : MIT Stability : experimental Portability : unknown Monadic representation of transactions. -} module Data.Transaction ( -- * Constructors action -- * Converters , reduce , toList , tMap , tFilter , tFilterMap -- * Types , Transaction , TransactionM ) where {- ============== - Types - ============== -} data TransactionM a x = TVal a (TransactionM a x) | TNull x deriving (Functor) type Transaction a = TransactionM a () instance Applicative (TransactionM a) where pure = TNull TVal a next <*> f = TVal a (next <*> f) TNull g <*> f = f >>= (pure . g) instance Monad (TransactionM a) where return = pure TVal a next >>= f = TVal a (next >>= f) TNull a >>= f = f a {- ============== - Operators - ============== -} {- | >>> :{ toList $ do action 4 action 5 action 6 :} [4,5,6] -} action :: a -> Transaction a action a = TVal a $ pure () {- ============== - Converters - ============== -} {- | >>> :{ toList $ do action 4 tMap (+1) $ do action 5 action 6 action 7 :} [4,6,7,7] -} tMap :: (a -> b) -> Transaction a -> Transaction b tMap f = tFilterMap (pure . f) {- | >>> :{ toList $ do action 4 tFilter even $ do action 5 action 6 action 7 :} [4,6,7] -} tFilter :: (a -> Bool) -> Transaction a -> Transaction a tFilter p = tFilterMap $ \a -> if p a then Just a else Nothing {- | >>> :{ toList $ do action 4 tFilterMap (\x -> if even x then Just (x + 1) else Nothing) $ do action 5 action 6 action 7 :} [4,7,7] -} tFilterMap :: (a -> Maybe b) -> Transaction a -> Transaction b tFilterMap f (TVal a next) = case f a of Just b -> TVal b $ tFilterMap f next Nothing -> tFilterMap f next tFilterMap _ (TNull ()) = TNull () reduce :: (b -> a -> b) -> b -> Transaction a -> b reduce f b (TVal a next) = reduce f (f b a) next reduce _ b (TNull ()) = b toList :: Transaction a -> [a] toList trans = reduce (\f a -> f . (a:)) id trans []