{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
module Control.FX.Monad.AppendOnly (
AppendOnly(..)
, runAppendOnly
, Context(..)
, Input(..)
, Output(..)
) where
import Data.Typeable (Typeable, typeOf)
import Control.FX.EqIn
import Control.FX.Functor
import Control.FX.Monad.Class
newtype AppendOnly
(mark :: * -> *)
(w :: *)
(a :: *)
= AppendOnly
{ unAppendOnly :: w -> Pair w a
} deriving (Typeable)
instance
( Typeable w, Typeable a, Typeable mark
) => Show (AppendOnly mark w a)
where
show
:: AppendOnly mark w a
-> String
show = show . typeOf
instance
( Monoid w, MonadIdentity mark
) => Functor (AppendOnly mark w)
where
fmap
:: (a -> b)
-> AppendOnly mark w a
-> AppendOnly mark w b
fmap f x =
x >>= (return . f)
instance
( Monoid w, MonadIdentity mark
) => Applicative (AppendOnly mark w)
where
pure
:: a
-> AppendOnly mark w a
pure a = AppendOnly $ \_ ->
Pair mempty a
(<*>)
:: AppendOnly mark w (a -> b)
-> AppendOnly mark w a
-> AppendOnly mark w b
(AppendOnly f') <*> (AppendOnly x') =
AppendOnly $ \w1 ->
let Pair w2 f = f' w1 in
let Pair w3 x = x' (w1 <> w2) in
Pair (w2 <> w3) (f x)
instance
( Monoid w, MonadIdentity mark
) => Monad (AppendOnly mark w)
where
return
:: a
-> AppendOnly mark w a
return a = AppendOnly $ \_ ->
Pair mempty a
(>>=)
:: AppendOnly mark w a
-> (a -> AppendOnly mark w b)
-> AppendOnly mark w b
(AppendOnly x') >>= f =
AppendOnly $ \w1 ->
let Pair w2 a = x' w1 in
let Pair w3 b = unAppendOnly (f a) (w1 <> w2) in
Pair (w2 <> w3) b
instance
( Monoid w, MonadIdentity mark
) => RunMonad (AppendOnly mark w)
where
newtype Input (AppendOnly mark w)
= AppendOnlyIn
{ unAppendOnlyIn :: mark ()
} deriving (Typeable)
newtype Output (AppendOnly mark w) a
= AppendOnlyOut
{ unAppendOnlyOut :: Pair (mark w) a
} deriving (Typeable)
run
:: Input (AppendOnly mark w)
-> AppendOnly mark w a
-> Output (AppendOnly mark w) a
run _ (AppendOnly x) = AppendOnlyOut $ bimap1 pure $ x mempty
runAppendOnly
:: ( Monoid w, MonadIdentity mark )
=> AppendOnly mark w a
-> Pair (mark w) a
runAppendOnly =
unAppendOnlyOut . run (AppendOnlyIn $ pure ())
deriving instance
( Eq (mark ())
) => Eq (Input (AppendOnly mark w))
deriving instance
( Show (mark ())
) => Show (Input (AppendOnly mark w))
deriving instance
( Eq (mark w), Eq a
) => Eq (Output (AppendOnly mark w) a)
deriving instance
( Show (mark w), Show a
) => Show (Output (AppendOnly mark w) a)
instance
( Eq w, Monoid w
) => EqIn (AppendOnly mark w)
where
newtype Context (AppendOnly mark w)
= AppendOnlyCtx
{ unAppendOnlyCtx :: mark ()
} deriving (Typeable)
eqIn
:: (Eq a)
=> Context (AppendOnly mark w)
-> AppendOnly mark w a
-> AppendOnly mark w a
-> Bool
eqIn _ (AppendOnly x) (AppendOnly y) =
(x mempty) == (y mempty)
deriving instance
( Eq (mark ())
) => Eq (Context (AppendOnly mark w))
deriving instance
( Show (mark ())
) => Show (Context (AppendOnly mark w))
instance
( Monoid w, MonadIdentity mark
) => MonadAppendOnly mark w (AppendOnly mark w)
where
look
:: AppendOnly mark w (mark w)
look = AppendOnly $ \w ->
Pair mempty (pure w)
jot
:: mark w
-> AppendOnly mark w ()
jot w = AppendOnly $ \_ ->
Pair (unwrap w) ()