{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
module Control.FX.Monad.State (
State(..)
, Context(..)
, Input(..)
, Output(..)
) where
import Data.Typeable (Typeable, typeOf)
import Control.FX.EqIn
import Control.FX.Functor
import Control.FX.Monad.Class
newtype State
(mark :: * -> *)
(s :: *)
(a :: *)
= State
{ unState :: s -> Pair s a
} deriving (Typeable)
instance
( Typeable s, Typeable a, Typeable mark
) => Show (State mark s a)
where
show
:: State mark s a
-> String
show = show . typeOf
instance
( MonadIdentity mark
) => Functor (State mark s)
where
fmap
:: (a -> b)
-> State mark s a
-> State mark s b
fmap f (State x) = State $ \s1 ->
let Pair s2 a = x s1 in
Pair s2 (f a)
instance
( MonadIdentity mark
) => Applicative (State mark s)
where
pure
:: a
-> State mark s a
pure a = State $ \s -> Pair s a
(<*>)
:: State mark s (a -> b)
-> State mark s a
-> State mark s b
(State f') <*> (State x') = State $ \s1 ->
let Pair s2 f = f' s1 in
let Pair s3 x = x' s2 in
Pair s3 (f x)
instance
( MonadIdentity mark
) => Monad (State mark s)
where
return
:: a
-> State mark s a
return a = State $ \s -> Pair s a
(>>=)
:: State mark s a
-> (a -> State mark s b)
-> State mark s b
(State x') >>= f = State $ \s1 ->
let Pair s2 x = x' s1 in
(unState . f) x s2
instance
( Eq s, MonadIdentity mark
) => EqIn (State mark s)
where
data Context (State mark s)
= StateCtx
{ unStateCtx :: mark s
} deriving (Typeable)
eqIn
:: (Eq a)
=> Context (State mark s)
-> State mark s a
-> State mark s a
-> Bool
eqIn (StateCtx s) (State x) (State y) =
(x $ unwrap s) == (y $ unwrap s)
deriving instance
( Eq (mark s)
) => Eq (Context (State mark s))
deriving instance
( Show (mark s)
) => Show (Context (State mark s))
instance
( MonadIdentity mark
) => RunMonad (State mark s)
where
data Input (State mark s)
= StateIn
{ unStateIn :: mark s
} deriving (Typeable)
data Output (State mark s) a
= StateOut
{ unStateOut :: Pair (mark s) a
} deriving (Typeable)
run
:: Input (State mark s)
-> State mark s a
-> Output (State mark s) a
run (StateIn s) (State x) =
let Pair s1 a = x (unwrap s)
in StateOut $ Pair (return s1) a
deriving instance
( Eq (mark s)
) => Eq (Input (State mark s))
deriving instance
( Show (mark s)
) => Show (Input (State mark s))
deriving instance
( Eq (mark s), Eq a
) => Eq (Output (State mark s) a)
deriving instance
( Show (mark s), Show a
) => Show (Output (State mark s) a)
instance
( MonadIdentity mark
) => MonadState mark s (State mark s)
where
get
:: State mark s (mark s)
get = State $ \s ->
Pair s (pure s)
put
:: mark s
-> State mark s ()
put s = State $ \_ ->
Pair (unwrap s) ()