{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
module Control.FX.Monad.Trans.WriteOnceT (
WriteOnceT(..)
, runWriteOnceT
, Context(..)
, InputT(..)
, OutputT(..)
) where
import Data.Typeable (Typeable, typeOf)
import Control.Monad (ap)
import Control.FX.EqIn
import Control.FX.Functor
import Control.FX.Monad
import Control.FX.Monad.Trans.Class
newtype WriteOnceT
(mark :: * -> *)
(w :: *)
(m :: * -> *)
(a :: *)
= WriteOnceT
{ unWriteOnceT :: LeftZero w -> m (Pair (LeftZero w) a)
} deriving (Typeable)
instance
( Typeable w, Typeable m, Typeable a, Typeable mark
) => Show (WriteOnceT mark w m a)
where
show
:: WriteOnceT mark w m a
-> String
show = show . typeOf
instance
( Monad m, MonadIdentity mark
) => Functor (WriteOnceT mark w m)
where
fmap
:: (a -> b)
-> WriteOnceT mark w m a
-> WriteOnceT mark w m b
fmap f x =
x >>= (return . f)
instance
( Monad m, MonadIdentity mark
) => Applicative (WriteOnceT mark w m)
where
pure
:: a
-> WriteOnceT mark w m a
pure = return
(<*>)
:: WriteOnceT mark w m (a -> b)
-> WriteOnceT mark w m a
-> WriteOnceT mark w m b
(<*>) = ap
instance
( Monad m, MonadIdentity mark
) => Monad (WriteOnceT mark w m)
where
return
:: a
-> WriteOnceT mark w m a
return x =
WriteOnceT $ \_ ->
return $ Pair mempty x
(>>=)
:: WriteOnceT mark w m a
-> (a -> WriteOnceT mark w m b)
-> WriteOnceT mark w m b
(WriteOnceT x) >>= f =
WriteOnceT $ \w1 -> do
Pair w2 a <- x w1
Pair w3 b <- unWriteOnceT (f a) (w1 <> w2)
return $ Pair (w2 <> w3) b
instance
( MonadIdentity mark
) => MonadTrans (WriteOnceT mark w)
where
lift
:: ( Monad m )
=> m a
-> WriteOnceT mark w m a
lift x = WriteOnceT $ \_ ->
fmap (\a -> Pair mempty a) x
instance
( MonadIdentity mark
) => MonadFunctor (WriteOnceT mark w)
where
hoist
:: ( Monad m, Monad n )
=> (forall u. m u -> n u)
-> WriteOnceT mark w m a
-> WriteOnceT mark w n a
hoist f (WriteOnceT x) =
WriteOnceT $ \w -> do
a <- f $ fmap slot2 (x w)
return $ Pair mempty a
instance
( EqIn m, MonadIdentity mark, Eq w
) => EqIn (WriteOnceT mark w m)
where
newtype Context (WriteOnceT mark w m)
= WriteOnceTCtx
{ unWriteOnceTCtx :: (mark (), Context m)
} deriving (Typeable)
eqIn
:: (Eq a)
=> Context (WriteOnceT mark w m)
-> WriteOnceT mark w m a
-> WriteOnceT mark w m a
-> Bool
eqIn (WriteOnceTCtx (w,h)) (WriteOnceT x) (WriteOnceT y) =
eqIn h (x mempty) (y mempty)
deriving instance
( Eq (mark ()), Eq (Context m)
) => Eq (Context (WriteOnceT mark w m))
deriving instance
( Show (mark ()), Show (Context m)
) => Show (Context (WriteOnceT mark w m))
instance
( MonadIdentity mark
) => RunMonadTrans (WriteOnceT mark w)
where
newtype InputT (WriteOnceT mark w)
= WriteOnceTIn
{ unWriteOnceTIn :: mark ()
} deriving (Typeable)
newtype OutputT (WriteOnceT mark w) a
= WriteOnceTOut
{ unWriteOnceTOut :: Pair (mark (Maybe w)) a
} deriving (Typeable)
runT
:: ( Monad m )
=> InputT (WriteOnceT mark w)
-> WriteOnceT mark w m a
-> m (OutputT (WriteOnceT mark w) a)
runT _ (WriteOnceT x) = do
Pair w a <- x mempty
return $ WriteOnceTOut $ Pair (pure $ toMaybe w) a
runWriteOnceT
:: ( Monad m, MonadIdentity mark )
=> WriteOnceT mark w m a
-> m (Pair (mark (Maybe w)) a)
runWriteOnceT =
fmap unWriteOnceTOut . runT (WriteOnceTIn $ pure ())
deriving instance
( Eq (mark ())
) => Eq (InputT (WriteOnceT mark w))
deriving instance
( Show (mark ())
) => Show (InputT (WriteOnceT mark w))
deriving instance
( Eq (mark (Maybe w)), Eq a
) => Eq (OutputT (WriteOnceT mark w) a)
deriving instance
( Show (mark (Maybe w)), Show a
) => Show (OutputT (WriteOnceT mark w) a)
instance
( MonadIdentity mark
) => LiftCatch (WriteOnceT mark w)
where
liftCatch
:: ( Monad m )
=> Catch e m (OutputT (WriteOnceT mark w) a)
-> Catch e (WriteOnceT mark w m) a
liftCatch catch x h = WriteOnceT $ \w ->
fmap (bimap1 (fromMaybe . unwrap) . unWriteOnceTOut) $ catch
(fmap (WriteOnceTOut . bimap1 (pure . toMaybe)) $ unWriteOnceT x w)
(\e -> fmap (WriteOnceTOut . bimap1 (pure . toMaybe)) $ unWriteOnceT (h e) w)
instance
( MonadIdentity mark
) => LiftDraft (WriteOnceT mark w)
where
liftDraft
:: ( Monad m )
=> Draft w1 m (OutputT (WriteOnceT mark w) a)
-> Draft w1 (WriteOnceT mark w m) a
liftDraft draft x =
WriteOnceT $ \w -> do
Pair w_ (WriteOnceTOut (Pair w1 a)) <-
draft $ fmap (WriteOnceTOut . bimap1 (pure . toMaybe)) $ unWriteOnceT x w
return $ Pair (fromMaybe $ unwrap w1) (Pair w_ a)
instance
( MonadIdentity mark
) => LiftLocal (WriteOnceT mark w)
where
liftLocal
:: ( Monad m )
=> Local r m (OutputT (WriteOnceT mark w) a)
-> Local r (WriteOnceT mark w m) a
liftLocal local f x =
WriteOnceT $ \w1 -> do
WriteOnceTOut (Pair w2 a) <-
local f $ fmap (WriteOnceTOut . bimap1 (pure . toMaybe)) $ unWriteOnceT x w1
return $ Pair (fromMaybe $ unwrap w2) a
instance {-# OVERLAPPING #-}
( Monad m, MonadIdentity mark
) => MonadWriteOnce mark w (WriteOnceT mark w m)
where
press
:: WriteOnceT mark w m (Maybe (mark w))
press = WriteOnceT $ \w ->
return (Pair mempty (fmap pure $ toMaybe w))
etch
:: mark w
-> WriteOnceT mark w m Bool
etch w = WriteOnceT $ \w1 ->
case w1 of
LeftUnit -> return $ Pair (LeftZero $ unwrap w) True
LeftZero _ -> return $ Pair mempty False
instance {-# OVERLAPPABLE #-}
( Monad m, MonadIdentity mark, MonadIdentity mark1
, MonadWriteOnce mark w m
) => MonadWriteOnce mark w (WriteOnceT mark1 w1 m)
instance
( Monad m, MonadIdentity mark, MonadIdentity mark1
, MonadState mark s m
) => MonadState mark s (WriteOnceT mark1 w m)
instance
( Monad m, MonadIdentity mark, MonadIdentity mark1
, MonadReadOnly mark r m
) => MonadReadOnly mark r (WriteOnceT mark1 w m)
instance
( Monad m, MonadIdentity mark, MonadIdentity mark1
, MonadAppendOnly mark w m
) => MonadAppendOnly mark w (WriteOnceT mark1 w1 m)
instance
( Monad m, MonadIdentity mark, MonadIdentity mark1
, MonadWriteOnly mark w m
) => MonadWriteOnly mark w (WriteOnceT mark1 w1 m)
instance
( Monad m, MonadIdentity mark, MonadIdentity mark1
, MonadExcept mark e m
) => MonadExcept mark e (WriteOnceT mark1 w m)
instance
( Monad m, MonadIdentity mark, MonadIdentity mark1
, MonadPrompt mark p m
) => MonadPrompt mark p (WriteOnceT mark1 w m)
instance
( Monad m, MonadIdentity mark1, MonadIdentity mark
, MonadHalt mark m
) => MonadHalt mark (WriteOnceT mark1 w m)