module Parameterized.Control.Monad.Trans.State.Strict where
import Control.Applicative
import Control.Monad
import qualified Control.Monad.Fail as Fail
import Control.Monad.Fix
import Control.Monad.IO.Class
import Control.Monad.Trans.State.Strict
import Data.Diverse
import qualified GHC.Generics as G
import Parameterized.Control.Monad
import Parameterized.TypeLevel
newtype ManyState m s a = ManyState
{ runManyState :: StateT s m a
} deriving ( G.Generic
, Functor
, Applicative
, Monad
, Alternative
, MonadPlus
, MonadFix
, Fail.MonadFail
, MonadIO
)
type instance PUnary (ManyState m) s = ManyState m s
instance Monad m => PPointed (ManyState m) (Many '[]) where
ppure = ManyState . pure
instance Alternative m => PEmpty (ManyState m) (Many '[]) where
pempty = ManyState $ StateT $ \_ -> empty
instance ( Monad m
, Select a c
, Select b c
, Amend' a c
, Amend' b c
, c ~ AppendUnique a b
) =>
PApplicative (ManyState m) (Many a) (Many b) (Many c) where
papply (ManyState (StateT x)) (ManyState (StateT y)) =
ManyState . StateT $ \c -> do
(f, a) <- x (select c)
let c' = amend' c a
(r, b) <- y (select c')
let c'' = amend' c' b
pure (f r, c'')
instance ( Monad m
, Alternative m
, Select a c
, Select b c
, Amend' a c
, Amend' b c
, c ~ AppendUnique a b
) =>
PAlternative (ManyState m) (Many a) (Many b) (Many c) where
pappend (ManyState (StateT x)) (ManyState (StateT y)) =
ManyState . StateT $ \c -> x' c <|> y' c
where
x' c = do
(r, a) <- x (select c)
pure (r, amend' c a)
y' c = do
(r, b) <- y (select c)
pure (r, amend' c b)
instance ( Monad m
, Select a c
, Select b c
, Amend' a c
, Amend' b c
, c ~ AppendUnique a b
) =>
PMonad (ManyState m) (Many a) (Many b) (Many c) where
pbind (ManyState (StateT x)) k =
ManyState . StateT $ \c -> do
(r, a) <- x (select c)
let c' = amend' c a
ManyState (StateT y) = k r
(r', b) <- y (select c')
let c'' = amend' c' b
pure (r', c'')
newtype ChangingState m st a = ChangingState
{ runChangingState :: At0 st -> m (a, At1 st)
} deriving (G.Generic)
changingState :: (s -> m (a, t)) -> ChangingState m (s, t) a
changingState = ChangingState
type instance PUnary (ChangingState m) st = ChangingState m st
instance Functor m => Functor (ChangingState m st) where
fmap f m = ChangingState $ \s ->
fmap (\(a, s') -> (f a, s')) $ runChangingState m s
instance Applicative m => PPointed (ChangingState m) (s, s) where
ppure a = ChangingState $ \s -> pure (a, s)
instance Monad m => PApplicative (ChangingState m) (s, t) (t, u) (s, u) where
papply (ChangingState x) (ChangingState y) =
ChangingState $ \s -> do
(f, t) <- x s
(r, u) <- y t
pure (f r, u)
instance Monad m => PMonad (ChangingState m) (s, t) (t, u) (s, u) where
pbind (ChangingState x) k =
ChangingState $ \s -> do
(r, t) <- x s
let ChangingState y = k r
(r', u) <- y t
pure (r', u)