{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE UndecidableInstances #-}
module Control.Carrier.Accum.Church
(
runAccum
, execAccum
, evalAccum
, AccumC(AccumC)
, module Control.Effect.Accum
) where
import Control.Algebra
import Control.Applicative (Alternative(..))
import Control.Effect.Accum
import Control.Monad (MonadPlus(..))
import Control.Monad.Fail as Fail
import Control.Monad.Fix
import Control.Monad.IO.Class
import Control.Monad.Trans.Class
runAccum :: (w -> a -> m b) -> w -> AccumC w m a -> m b
runAccum :: forall w a (m :: * -> *) b.
(w -> a -> m b) -> w -> AccumC w m a -> m b
runAccum w -> a -> m b
k w
w AccumC w m a
ma = forall w (m :: * -> *) a.
AccumC w m a -> forall r. (w -> a -> m r) -> w -> m r
runAccumC AccumC w m a
ma w -> a -> m b
k w
w
{-# INLINE runAccum #-}
execAccum :: Applicative m => w -> AccumC w m a -> m w
execAccum :: forall (m :: * -> *) w a. Applicative m => w -> AccumC w m a -> m w
execAccum = forall w a (m :: * -> *) b.
(w -> a -> m b) -> w -> AccumC w m a -> m b
runAccum (forall a b. a -> b -> a
const forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) a. Applicative f => a -> f a
pure)
{-# INLINE execAccum #-}
evalAccum :: Applicative m => w -> AccumC w m a -> m a
evalAccum :: forall (m :: * -> *) w a. Applicative m => w -> AccumC w m a -> m a
evalAccum = forall w a (m :: * -> *) b.
(w -> a -> m b) -> w -> AccumC w m a -> m b
runAccum forall a b. (a -> b) -> a -> b
$ forall a b. a -> b -> a
const forall (f :: * -> *) a. Applicative f => a -> f a
pure
{-# INLINE evalAccum #-}
newtype AccumC w m a = AccumC { forall w (m :: * -> *) a.
AccumC w m a -> forall r. (w -> a -> m r) -> w -> m r
runAccumC :: forall r . (w -> a -> m r) -> w -> m r }
instance Monoid w => MonadTrans (AccumC w) where
lift :: forall (m :: * -> *) a. Monad m => m a -> AccumC w m a
lift m a
ma = forall w (m :: * -> *) a.
(forall r. (w -> a -> m r) -> w -> m r) -> AccumC w m a
AccumC forall a b. (a -> b) -> a -> b
$ \w -> a -> m r
k w
_ -> m a
ma forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= w -> a -> m r
k forall a. Monoid a => a
mempty
{-# INLINE lift #-}
instance Functor (AccumC w m) where
fmap :: forall a b. (a -> b) -> AccumC w m a -> AccumC w m b
fmap a -> b
f AccumC w m a
ma = forall w (m :: * -> *) a.
(forall r. (w -> a -> m r) -> w -> m r) -> AccumC w m a
AccumC forall a b. (a -> b) -> a -> b
$ \w -> b -> m r
k w
w -> forall w (m :: * -> *) a.
AccumC w m a -> forall r. (w -> a -> m r) -> w -> m r
runAccumC AccumC w m a
ma (\w
w a
a -> w -> b -> m r
k w
w forall a b. (a -> b) -> a -> b
$ a -> b
f a
a) w
w
{-# INLINE fmap #-}
instance Monoid w => Applicative (AccumC w m) where
pure :: forall a. a -> AccumC w m a
pure a
a = forall w (m :: * -> *) a.
(forall r. (w -> a -> m r) -> w -> m r) -> AccumC w m a
AccumC forall a b. (a -> b) -> a -> b
$ \w -> a -> m r
k w
_ -> w -> a -> m r
k forall a. Monoid a => a
mempty a
a
{-# INLINE pure #-}
AccumC w m (a -> b)
mf <*> :: forall a b. AccumC w m (a -> b) -> AccumC w m a -> AccumC w m b
<*> AccumC w m a
ma = forall w (m :: * -> *) a.
(forall r. (w -> a -> m r) -> w -> m r) -> AccumC w m a
AccumC forall a b. (a -> b) -> a -> b
$ \w -> b -> m r
k w
w ->
forall w (m :: * -> *) a.
AccumC w m a -> forall r. (w -> a -> m r) -> w -> m r
runAccumC AccumC w m (a -> b)
mf (\w
w' a -> b
f -> forall w (m :: * -> *) a.
AccumC w m a -> forall r. (w -> a -> m r) -> w -> m r
runAccumC AccumC w m a
ma (\w
w'' a
a -> w -> b -> m r
k (w
w' forall a. Monoid a => a -> a -> a
`mappend` w
w'') forall a b. (a -> b) -> a -> b
$ a -> b
f a
a) (w
w forall a. Monoid a => a -> a -> a
`mappend` w
w')) w
w
{-# INLINE (<*>) #-}
instance (Alternative m, Monad m, Monoid w) => Alternative (AccumC w m) where
empty :: forall a. AccumC w m a
empty = forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift forall (f :: * -> *) a. Alternative f => f a
empty
{-# INLINE empty #-}
AccumC w m a
ma1 <|> :: forall a. AccumC w m a -> AccumC w m a -> AccumC w m a
<|> AccumC w m a
ma2 = forall w (m :: * -> *) a.
(forall r. (w -> a -> m r) -> w -> m r) -> AccumC w m a
AccumC forall a b. (a -> b) -> a -> b
$ \w -> a -> m r
k w
w -> forall w (m :: * -> *) a.
AccumC w m a -> forall r. (w -> a -> m r) -> w -> m r
runAccumC AccumC w m a
ma1 w -> a -> m r
k w
w forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> forall w (m :: * -> *) a.
AccumC w m a -> forall r. (w -> a -> m r) -> w -> m r
runAccumC AccumC w m a
ma2 w -> a -> m r
k w
w
{-# INLINE (<|>) #-}
instance (Monad m, Monoid w) => Monad (AccumC w m) where
AccumC w m a
ma >>= :: forall a b. AccumC w m a -> (a -> AccumC w m b) -> AccumC w m b
>>= a -> AccumC w m b
f = forall w (m :: * -> *) a.
(forall r. (w -> a -> m r) -> w -> m r) -> AccumC w m a
AccumC forall a b. (a -> b) -> a -> b
$ \w -> b -> m r
k w
w -> forall w (m :: * -> *) a.
AccumC w m a -> forall r. (w -> a -> m r) -> w -> m r
runAccumC AccumC w m a
ma (\w
w' a
a -> forall w (m :: * -> *) a.
AccumC w m a -> forall r. (w -> a -> m r) -> w -> m r
runAccumC (a -> AccumC w m b
f a
a) (\w
w'' -> w -> b -> m r
k forall a b. (a -> b) -> a -> b
$ w
w' forall a. Monoid a => a -> a -> a
`mappend` w
w'') (w
w forall a. Monoid a => a -> a -> a
`mappend` w
w')) w
w
{-# INLINE (>>=) #-}
instance (MonadPlus m, Monoid w) => MonadPlus (AccumC w m) where
mzero :: forall a. AccumC w m a
mzero = forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift forall (m :: * -> *) a. MonadPlus m => m a
mzero
{-# INLINE mzero #-}
AccumC w m a
ma1 mplus :: forall a. AccumC w m a -> AccumC w m a -> AccumC w m a
`mplus` AccumC w m a
ma2 = forall w (m :: * -> *) a.
(forall r. (w -> a -> m r) -> w -> m r) -> AccumC w m a
AccumC forall a b. (a -> b) -> a -> b
$ \w -> a -> m r
k w
w -> forall w (m :: * -> *) a.
AccumC w m a -> forall r. (w -> a -> m r) -> w -> m r
runAccumC AccumC w m a
ma1 w -> a -> m r
k w
w forall (m :: * -> *) a. MonadPlus m => m a -> m a -> m a
`mplus` forall w (m :: * -> *) a.
AccumC w m a -> forall r. (w -> a -> m r) -> w -> m r
runAccumC AccumC w m a
ma2 w -> a -> m r
k w
w
{-# INLINE mplus #-}
instance (MonadFail m, Monoid w) => MonadFail (AccumC w m) where
fail :: forall a. String -> AccumC w m a
fail String
msg = forall w (m :: * -> *) a.
(forall r. (w -> a -> m r) -> w -> m r) -> AccumC w m a
AccumC forall a b. (a -> b) -> a -> b
$ forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. MonadFail m => String -> m a
Fail.fail String
msg
{-# INLINE fail #-}
instance (MonadFix m, Monoid w) => MonadFix (AccumC w m) where
mfix :: forall a. (a -> AccumC w m a) -> AccumC w m a
mfix a -> AccumC w m a
ma = forall w (m :: * -> *) a.
(forall r. (w -> a -> m r) -> w -> m r) -> AccumC w m a
AccumC forall a b. (a -> b) -> a -> b
$ \ w -> a -> m r
k w
w -> forall (m :: * -> *) a. MonadFix m => (a -> m a) -> m a
mfix ((\AccumC w m a
accumC -> forall w (m :: * -> *) a.
AccumC w m a -> forall r. (w -> a -> m r) -> w -> m r
runAccumC AccumC w m a
accumC (forall a b c. ((a, b) -> c) -> a -> b -> c
curry forall (f :: * -> *) a. Applicative f => a -> f a
pure) w
w) forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> AccumC w m a
ma forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> b
snd) forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry w -> a -> m r
k
{-# INLINE mfix #-}
instance (MonadIO m, Monoid w) => MonadIO (AccumC w m) where
liftIO :: forall a. IO a -> AccumC w m a
liftIO = forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO
{-# INLINE liftIO #-}
instance (Algebra sig m, Monoid w) => Algebra (Accum w :+: sig) (AccumC w m) where
alg :: forall (ctx :: * -> *) (n :: * -> *) a.
Functor ctx =>
Handler ctx n (AccumC w m)
-> (:+:) (Accum w) sig n a -> ctx () -> AccumC w m (ctx a)
alg Handler ctx n (AccumC w m)
hdl (:+:) (Accum w) sig n a
sig ctx ()
ctx = forall w (m :: * -> *) a.
(forall r. (w -> a -> m r) -> w -> m r) -> AccumC w m a
AccumC forall a b. (a -> b) -> a -> b
$ \w -> ctx a -> m r
k w
w -> case (:+:) (Accum w) sig n a
sig of
L Accum w n a
accum -> case Accum w n a
accum of
Add w
w' -> w -> ctx a -> m r
k w
w' ctx ()
ctx
Accum w n a
Look -> w -> ctx a -> m r
k forall a. Monoid a => a
mempty forall a b. (a -> b) -> a -> b
$ w
w forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ ctx ()
ctx
R sig n a
other -> forall (ctx1 :: * -> *) (ctx2 :: * -> *)
(sig :: (* -> *) -> * -> *) (m :: * -> *) (n :: * -> *) a.
(Functor ctx1, Functor ctx2, Algebra sig m) =>
Handler (Compose ctx1 ctx2) n m
-> sig n a -> ctx1 (ctx2 ()) -> m (ctx1 (ctx2 a))
thread (forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry (forall w a (m :: * -> *) b.
(w -> a -> m b) -> w -> AccumC w m a -> m b
runAccum (forall a b c. ((a, b) -> c) -> a -> b -> c
curry forall (f :: * -> *) a. Applicative f => a -> f a
pure)) forall (n :: * -> *) (ctx1 :: * -> *) (m :: * -> *)
(ctx2 :: * -> *) (l :: * -> *).
(Functor n, Functor ctx1) =>
Handler ctx1 m n
-> Handler ctx2 l m -> Handler (Compose ctx1 ctx2) l n
~<~ Handler ctx n (AccumC w m)
hdl) sig n a
other (w
w, ctx ()
ctx) forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry w -> ctx a -> m r
k
{-# INLINE alg #-}