module Control.Inventory.State (State (..)) where import "morphisms" Control.Morphism (($), (.)) import "morphisms-functors" Control.Variance ((:.:), Variant (Co, Contra)) import "morphisms-functors" Control.Functor.Covariant (Covariant ((<$>), comap)) import "morphisms-functors" Control.Functor.Covariant.Pointable (Pointable (point)) import "morphisms-functors" Control.Functor.Covariant.Applicative (Applicative ((<*>))) import "morphisms-functors" Control.Functor.Covariant.Composition.Bindable (Bindable ((>>=))) import "morphisms-functors" Control.Functor.Covariant.Composition.Monad (Monad) import "morphisms-functors" Data.Functor.Arrow.Straight (Straight (Straight, straight)) import "morphisms-functors" Data.Functor.Product (Product ((:&:))) import "morphisms-functors" Data.Functor.Composition.TT (TT (TT, tt)) newtype State (s :: *) (g :: * -> *) (a :: *) = State { state :: Straight s (g (Product s a)) } instance Covariant g => Covariant (State s g) where f <$> State x = State . tt . comap f $ TT @Co @Co @Co x instance Monad g => Applicative (State s g) where State (Straight f) <*> State (Straight x) = State . Straight $ \old -> f old >>= \(new :&: g) -> comap g <$> x new instance Pointable g => Pointable (State s g) where point x = State . Straight $ \s -> point $ s :&: x instance Bindable g => Bindable (State s g) where State (Straight x) >>= f = State . Straight $ \old -> x old >>= \(new :&: y) -> straight (state $ f y) new instance Monad g => Monad (State s g) where