{-# LANGUAGE UnboxedTuples #-}
{-# OPTIONS_HADDOCK not-home #-}
module Cleff.Internal.Monad
(
Effect
, type (:>)
, type (:>>)
, type (~>)
, type (++)
, InternalHandler (InternalHandler, runHandler)
, Eff (Eff, unEff)
, Env
, HandlerPtr
, emptyEnv
, adjustEnv
, allocaEnv
, readEnv
, writeEnv
, replaceEnv
, appendEnv
, updateEnv
, KnownList
, Subset
, send
, sendVia
) where
import Cleff.Internal.Any (Any, fromAny, toAny)
import Cleff.Internal.Rec (Elem, KnownList, Rec, Subset, type (++))
import qualified Cleff.Internal.Rec as Rec
import Control.Applicative (Applicative (liftA2))
import Control.Monad.Fix (MonadFix (mfix))
import Data.IntMap.Strict (IntMap)
import qualified Data.IntMap.Strict as Map
import Data.Kind (Constraint, Type)
type Effect = (Type -> Type) -> Type -> Type
type (:>) = Elem
infix 0 :>
type family xs :>> es :: Constraint where
'[] :>> _ = ()
(x ': xs) :>> es = (x :> es, xs :>> es)
infix 0 :>>
type f ~> g = ∀ a. f a -> g a
newtype InternalHandler e = InternalHandler { InternalHandler e
-> forall (es :: [Effect]) a. e (Eff es) a -> Eff es a
runHandler :: ∀ es. e (Eff es) ~> Eff es }
type role Eff nominal representational
newtype Eff es a = Eff { Eff es a -> Env es -> IO a
unEff :: Env es -> IO a }
instance Functor (Eff es) where
fmap :: (a -> b) -> Eff es a -> Eff es b
fmap a -> b
f (Eff Env es -> IO a
x) = (Env es -> IO b) -> Eff es b
forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
Eff ((a -> b) -> IO a -> IO b
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> b
f (IO a -> IO b) -> (Env es -> IO a) -> Env es -> IO b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Env es -> IO a
x)
{-# INLINE fmap #-}
a
x <$ :: a -> Eff es b -> Eff es a
<$ Eff Env es -> IO b
y = (Env es -> IO a) -> Eff es a
forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
Eff \Env es
es -> a
x a -> IO b -> IO a
forall (f :: Type -> Type) a b. Functor f => a -> f b -> f a
<$ Env es -> IO b
y Env es
es
{-# INLINE (<$) #-}
instance Applicative (Eff es) where
pure :: a -> Eff es a
pure = (Env es -> IO a) -> Eff es a
forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
Eff ((Env es -> IO a) -> Eff es a)
-> (a -> Env es -> IO a) -> a -> Eff es a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO a -> Env es -> IO a
forall a b. a -> b -> a
const (IO a -> Env es -> IO a) -> (a -> IO a) -> a -> Env es -> IO a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> IO a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure
{-# INLINE pure #-}
Eff Env es -> IO (a -> b)
f <*> :: Eff es (a -> b) -> Eff es a -> Eff es b
<*> Eff Env es -> IO a
x = (Env es -> IO b) -> Eff es b
forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
Eff \Env es
es -> Env es -> IO (a -> b)
f Env es
es IO (a -> b) -> IO a -> IO b
forall (f :: Type -> Type) a b.
Applicative f =>
f (a -> b) -> f a -> f b
<*> Env es -> IO a
x Env es
es
{-# INLINE (<*>) #-}
Eff Env es -> IO a
x <* :: Eff es a -> Eff es b -> Eff es a
<* Eff Env es -> IO b
y = (Env es -> IO a) -> Eff es a
forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
Eff \Env es
es -> Env es -> IO a
x Env es
es IO a -> IO b -> IO a
forall (f :: Type -> Type) a b. Applicative f => f a -> f b -> f a
<* Env es -> IO b
y Env es
es
{-# INLINE (<*) #-}
Eff Env es -> IO a
x *> :: Eff es a -> Eff es b -> Eff es b
*> Eff Env es -> IO b
y = (Env es -> IO b) -> Eff es b
forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
Eff \Env es
es -> Env es -> IO a
x Env es
es IO a -> IO b -> IO b
forall (f :: Type -> Type) a b. Applicative f => f a -> f b -> f b
*> Env es -> IO b
y Env es
es
{-# INLINE (*>) #-}
liftA2 :: (a -> b -> c) -> Eff es a -> Eff es b -> Eff es c
liftA2 a -> b -> c
f (Eff Env es -> IO a
x) (Eff Env es -> IO b
y) = (Env es -> IO c) -> Eff es c
forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
Eff \Env es
es -> (a -> b -> c) -> IO a -> IO b -> IO c
forall (f :: Type -> Type) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 a -> b -> c
f (Env es -> IO a
x Env es
es) (Env es -> IO b
y Env es
es)
{-# INLINE liftA2 #-}
instance Monad (Eff es) where
Eff Env es -> IO a
x >>= :: Eff es a -> (a -> Eff es b) -> Eff es b
>>= a -> Eff es b
f = (Env es -> IO b) -> Eff es b
forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
Eff \Env es
es -> Env es -> IO a
x Env es
es IO a -> (a -> IO b) -> IO b
forall (m :: Type -> Type) a b. Monad m => m a -> (a -> m b) -> m b
>>= \a
x' -> Eff es b -> Env es -> IO b
forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff (a -> Eff es b
f a
x') Env es
es
{-# INLINE (>>=) #-}
>> :: Eff es a -> Eff es b -> Eff es b
(>>) = Eff es a -> Eff es b -> Eff es b
forall (f :: Type -> Type) a b. Applicative f => f a -> f b -> f b
(*>)
{-# INLINE (>>) #-}
instance MonadFix (Eff es) where
mfix :: (a -> Eff es a) -> Eff es a
mfix a -> Eff es a
f = (Env es -> IO a) -> Eff es a
forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
Eff \Env es
es -> (a -> IO a) -> IO a
forall (m :: Type -> Type) a. MonadFix m => (a -> m a) -> m a
mfix \a
x -> Eff es a -> Env es -> IO a
forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff (a -> Eff es a
f a
x) Env es
es
{-# INLINE mfix #-}
type role Env nominal
data Env (es :: [Effect]) = Env
{-# UNPACK #-} !Int
{-# UNPACK #-} !(Rec HandlerPtr es)
!(IntMap Any)
type role HandlerPtr nominal
newtype HandlerPtr (e :: Effect) = HandlerPtr { HandlerPtr e -> Int
unHandlerPtr :: Int }
emptyEnv :: Env '[]
emptyEnv :: Env '[]
emptyEnv = Int -> Rec HandlerPtr '[] -> IntMap Any -> Env '[]
forall (es :: [Effect]).
Int -> Rec HandlerPtr es -> IntMap Any -> Env es
Env Int
0 Rec HandlerPtr '[]
forall k (f :: k -> Type). Rec f '[]
Rec.empty IntMap Any
forall a. IntMap a
Map.empty
{-# INLINE emptyEnv #-}
adjustEnv :: ∀ es' es. (Rec HandlerPtr es -> Rec HandlerPtr es') -> Env es -> Env es'
adjustEnv :: (Rec HandlerPtr es -> Rec HandlerPtr es') -> Env es -> Env es'
adjustEnv Rec HandlerPtr es -> Rec HandlerPtr es'
f (Env Int
n Rec HandlerPtr es
re IntMap Any
mem) = Int -> Rec HandlerPtr es' -> IntMap Any -> Env es'
forall (es :: [Effect]).
Int -> Rec HandlerPtr es -> IntMap Any -> Env es
Env Int
n (Rec HandlerPtr es -> Rec HandlerPtr es'
f Rec HandlerPtr es
re) IntMap Any
mem
{-# INLINE adjustEnv #-}
allocaEnv :: ∀ e es. Env es -> (# HandlerPtr e, Env es #)
allocaEnv :: Env es -> (# HandlerPtr e, Env es #)
allocaEnv (Env Int
n Rec HandlerPtr es
re IntMap Any
mem) = (# Int -> HandlerPtr e
forall (e :: Effect). Int -> HandlerPtr e
HandlerPtr Int
n, Int -> Rec HandlerPtr es -> IntMap Any -> Env es
forall (es :: [Effect]).
Int -> Rec HandlerPtr es -> IntMap Any -> Env es
Env (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) Rec HandlerPtr es
re IntMap Any
mem #)
{-# INLINE allocaEnv #-}
readEnv :: ∀ e es. Rec.Elem e es => Env es -> InternalHandler e
readEnv :: Env es -> InternalHandler e
readEnv (Env Int
_ Rec HandlerPtr es
re IntMap Any
mem) = Any -> InternalHandler e
forall a. Any -> a
fromAny (Any -> InternalHandler e) -> Any -> InternalHandler e
forall a b. (a -> b) -> a -> b
$ IntMap Any
mem IntMap Any -> Int -> Any
forall a. IntMap a -> Int -> a
Map.! HandlerPtr e -> Int
forall (e :: Effect). HandlerPtr e -> Int
unHandlerPtr (Rec HandlerPtr es -> HandlerPtr e
forall k (e :: k) (es :: [k]) (f :: k -> Type).
Elem e es =>
Rec f es -> f e
Rec.index @e Rec HandlerPtr es
re)
{-# INLINE readEnv #-}
writeEnv :: ∀ e es. HandlerPtr e -> InternalHandler e -> Env es -> Env es
writeEnv :: HandlerPtr e -> InternalHandler e -> Env es -> Env es
writeEnv (HandlerPtr Int
m) InternalHandler e
x (Env Int
n Rec HandlerPtr es
re IntMap Any
mem) = Int -> Rec HandlerPtr es -> IntMap Any -> Env es
forall (es :: [Effect]).
Int -> Rec HandlerPtr es -> IntMap Any -> Env es
Env Int
n Rec HandlerPtr es
re (Int -> Any -> IntMap Any -> IntMap Any
forall a. Int -> a -> IntMap a -> IntMap a
Map.insert Int
m (InternalHandler e -> Any
forall a. a -> Any
toAny InternalHandler e
x) IntMap Any
mem)
{-# INLINE writeEnv #-}
replaceEnv :: ∀ e es. Rec.Elem e es => HandlerPtr e -> InternalHandler e -> Env es -> Env es
replaceEnv :: HandlerPtr e -> InternalHandler e -> Env es -> Env es
replaceEnv (HandlerPtr Int
m) InternalHandler e
x (Env Int
n Rec HandlerPtr es
re IntMap Any
mem) = Int -> Rec HandlerPtr es -> IntMap Any -> Env es
forall (es :: [Effect]).
Int -> Rec HandlerPtr es -> IntMap Any -> Env es
Env Int
n (HandlerPtr e -> Rec HandlerPtr es -> Rec HandlerPtr es
forall k (e :: k) (es :: [k]) (f :: k -> Type).
Elem e es =>
f e -> Rec f es -> Rec f es
Rec.update @e (Int -> HandlerPtr e
forall (e :: Effect). Int -> HandlerPtr e
HandlerPtr Int
m) Rec HandlerPtr es
re) (Int -> Any -> IntMap Any -> IntMap Any
forall a. Int -> a -> IntMap a -> IntMap a
Map.insert Int
m (InternalHandler e -> Any
forall a. a -> Any
toAny InternalHandler e
x) IntMap Any
mem)
{-# INLINE replaceEnv #-}
appendEnv :: ∀ e es. HandlerPtr e -> InternalHandler e -> Env es -> Env (e ': es)
appendEnv :: HandlerPtr e -> InternalHandler e -> Env es -> Env (e : es)
appendEnv (HandlerPtr Int
m) InternalHandler e
x (Env Int
n Rec HandlerPtr es
re IntMap Any
mem) = Int -> Rec HandlerPtr (e : es) -> IntMap Any -> Env (e : es)
forall (es :: [Effect]).
Int -> Rec HandlerPtr es -> IntMap Any -> Env es
Env Int
n (HandlerPtr e -> Rec HandlerPtr es -> Rec HandlerPtr (e : es)
forall a (f :: a -> Type) (e :: a) (es :: [a]).
f e -> Rec f es -> Rec f (e : es)
Rec.cons (Int -> HandlerPtr e
forall (e :: Effect). Int -> HandlerPtr e
HandlerPtr Int
m) Rec HandlerPtr es
re) (Int -> Any -> IntMap Any -> IntMap Any
forall a. Int -> a -> IntMap a -> IntMap a
Map.insert Int
m (InternalHandler e -> Any
forall a. a -> Any
toAny InternalHandler e
x) IntMap Any
mem)
{-# INLINE appendEnv #-}
updateEnv :: ∀ es es'. Env es' -> Env es -> Env es
updateEnv :: Env es' -> Env es -> Env es
updateEnv (Env Int
n Rec HandlerPtr es'
_ IntMap Any
mem) (Env Int
_ Rec HandlerPtr es
re' IntMap Any
_) = Int -> Rec HandlerPtr es -> IntMap Any -> Env es
forall (es :: [Effect]).
Int -> Rec HandlerPtr es -> IntMap Any -> Env es
Env Int
n Rec HandlerPtr es
re' IntMap Any
mem
{-# INLINE updateEnv #-}
send :: e :> es => e (Eff es) ~> Eff es
send :: e (Eff es) ~> Eff es
send = (Eff es ~> Eff es) -> e (Eff es) ~> Eff es
forall (e :: Effect) (es' :: [Effect]) (es :: [Effect]).
(e :> es') =>
(Eff es ~> Eff es') -> e (Eff es) ~> Eff es'
sendVia forall a. a -> a
Eff es ~> Eff es
id
sendVia :: e :> es' => (Eff es ~> Eff es') -> e (Eff es) ~> Eff es'
sendVia :: (Eff es ~> Eff es') -> e (Eff es) ~> Eff es'
sendVia Eff es ~> Eff es'
f e (Eff es) a
e = (Env es' -> IO a) -> Eff es' a
forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
Eff \Env es'
es -> Eff es' a -> Env es' -> IO a
forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff (Eff es a -> Eff es' a
Eff es ~> Eff es'
f (InternalHandler e -> e (Eff es) a -> Eff es a
forall (e :: Effect).
InternalHandler e
-> forall (es :: [Effect]) a. e (Eff es) a -> Eff es a
runHandler (Env es' -> InternalHandler e
forall (e :: Effect) (es :: [Effect]).
Elem e es =>
Env es -> InternalHandler e
readEnv Env es'
es) e (Eff es) a
e)) Env es'
es