{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
module Control.FX.Monad.ReadOnly (
ReadOnly(..)
, Context(..)
, Input(..)
, Output(..)
) where
import Data.Typeable (Typeable, typeOf)
import Control.FX.EqIn
import Control.FX.Functor
import Control.FX.Monad.Class
import Control.FX.Monad.Identity
newtype ReadOnly
(mark :: * -> *)
(r :: *)
(a :: *)
= ReadOnly
{ unReadOnly :: r -> a
} deriving (Typeable)
instance
( Typeable r, Typeable a, Typeable mark
) => Show (ReadOnly mark r a)
where
show
:: ReadOnly mark r a
-> String
show = show . typeOf
instance
( MonadIdentity mark
) => Functor (ReadOnly mark r)
where
fmap
:: (a -> b)
-> ReadOnly mark r a
-> ReadOnly mark r b
fmap f (ReadOnly x) = ReadOnly (f . x)
instance
( MonadIdentity mark
) => Applicative (ReadOnly mark r)
where
pure
:: a
-> ReadOnly mark r a
pure = ReadOnly . const
(<*>)
:: ReadOnly mark r (a -> b)
-> ReadOnly mark r a
-> ReadOnly mark r b
(ReadOnly f) <*> (ReadOnly x) =
ReadOnly $ \r -> (f r) (x r)
instance
( MonadIdentity mark
) => Monad (ReadOnly mark r)
where
return
:: a
-> ReadOnly mark r a
return x = ReadOnly $ \_ -> x
(>>=)
:: ReadOnly mark r a
-> (a -> ReadOnly mark r b)
-> ReadOnly mark r b
(ReadOnly x) >>= f = ReadOnly $ \r ->
let a = x r
in unReadOnly (f a) r
instance
( MonadIdentity mark
) => EqIn (ReadOnly mark r)
where
newtype Context (ReadOnly mark r)
= ReadOnlyCtx
{ unReadOnlyCtx :: mark r
} deriving (Typeable)
eqIn
:: (Eq a)
=> Context (ReadOnly mark r)
-> ReadOnly mark r a
-> ReadOnly mark r a
-> Bool
eqIn (ReadOnlyCtx r) (ReadOnly x) (ReadOnly y) =
(x $ unwrap r) == (y $ unwrap r)
deriving instance
( Eq (mark r)
) => Eq (Context (ReadOnly mark r))
deriving instance
( Show (mark r)
) => Show (Context (ReadOnly mark r))
instance
( MonadIdentity mark, Commutant mark
) => RunMonad (ReadOnly mark r)
where
newtype Input (ReadOnly mark r)
= ReadOnlyIn
{ unReadOnlyIn :: mark r
} deriving (Typeable)
newtype Output (ReadOnly mark r) a
= ReadOnlyOut
{ unReadOnlyOut :: mark a
} deriving (Typeable)
run
:: Input (ReadOnly mark r)
-> ReadOnly mark r a
-> Output (ReadOnly mark r) a
run (ReadOnlyIn r) (ReadOnly x) =
ReadOnlyOut $ pure (x (unwrap r))
deriving instance
( Eq (mark r)
) => Eq (Input (ReadOnly mark r))
deriving instance
( Show (mark r)
) => Show (Input (ReadOnly mark r))
deriving instance
( Eq (mark a)
) => Eq (Output (ReadOnly mark r) a)
deriving instance
( Show (mark a)
) => Show (Output (ReadOnly mark r) a)
instance
( MonadIdentity mark
) => MonadReadOnly mark r (ReadOnly mark r)
where
ask
:: ReadOnly mark r (mark r)
ask = ReadOnly pure
local
:: (mark r -> mark r)
-> ReadOnly mark r a
-> ReadOnly mark r a
local f (ReadOnly x) = ReadOnly $ \r ->
x (unwrap $ f $ pure r)