{-# LANGUAGE Trustworthy #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE CPP #-}
module Control.Eff.Internal ( module Control.Eff.Internal
) where
#if __GLASGOW_HASKELL__ < 710
import Control.Applicative
#endif
import qualified Control.Arrow as A
import qualified Control.Category as C
import Control.Monad.Base (MonadBase(..))
import Control.Monad.IO.Class (MonadIO(..))
import Control.Monad.Trans.Control (MonadBaseControl(..))
import safe Data.OpenUnion
import safe Data.FTCQueue
import GHC.Exts (inline)
type Arr r a b = a -> Eff r b
newtype Arrs r a b = Arrs (FTCQueue (Eff r) a b)
instance C.Category (Arrs r) where
id = ident
f . g = comp g f
instance A.Arrow (Arrs r) where
arr = arr
first = singleK . first . (^$)
first :: Arr r a b -> Arr r (a, c) (b, c)
first x = \(a,c) -> (, c) `fmap` x a
{-# INLINE singleK #-}
singleK :: Arr r a b -> Arrs r a b
singleK = Arrs . tsingleton
{-# INLINABLE qApp #-}
qApp :: forall r b w. Arrs r b w -> Arr r b w
qApp (Arrs q) x = viewlMap (inline tviewl q) ($ x) cons
where
cons :: forall x. Arr r b x -> FTCQueue (Eff r) x w -> Eff r w
cons = \k t -> case k x of
Val y -> qApp (Arrs t) y
E u (Arrs q0) -> E u (Arrs (q0 >< t))
{-# INLINABLE (^$) #-}
(^$) :: forall r b w. Arrs r b w -> Arr r b w
q ^$ x = q `qApp` x
arr :: (a -> b) -> Arrs r a b
arr f = singleK (Val . f)
ident :: Arrs r a a
ident = arr id
comp :: Arrs r a b -> Arrs r b c -> Arrs r a c
comp (Arrs f) (Arrs g) = Arrs (f >< g)
(^|>) :: Arrs r a b -> Arr r b c -> Arrs r a c
(Arrs f) ^|> g = Arrs (f |> g)
data Eff r a = Val a
| forall b. E (Union r b) (Arrs r b a)
{-# INLINE qComp #-}
qComp :: Arrs r a b -> (Eff r b -> Eff r' c) -> Arr r' a c
qComp g h = \a -> h $ (g ^$ a)
{-# INLINE qComps #-}
qComps :: Arrs r a b -> (Eff r b -> Eff r' c) -> Arrs r' a c
qComps g h = singleK $ qComp g h
instance Functor (Eff r) where
{-# INLINE fmap #-}
fmap f (Val x) = Val (f x)
fmap f (E u q) = E u (q ^|> (Val . f))
instance Applicative (Eff r) where
{-# INLINE pure #-}
pure = Val
Val f <*> e = f `fmap` e
E u q <*> e = E u (q ^|> (`fmap` e))
instance Monad (Eff r) where
{-# INLINE return #-}
{-# INLINE [2] (>>=) #-}
return = pure
Val x >>= k = k x
E u q >>= k = E u (q ^|> k)
instance (MonadBase b m, SetMember Lift (Lift m) r) => MonadBase b (Eff r) where
liftBase = lift . liftBase
{-# INLINE liftBase #-}
instance (MonadBase m m) => MonadBaseControl m (Eff '[Lift m]) where
type StM (Eff '[Lift m]) a = a
liftBaseWith f = lift (f runLift)
{-# INLINE liftBaseWith #-}
restoreM = return
{-# INLINE restoreM #-}
instance (MonadIO m, SetMember Lift (Lift m) r) => MonadIO (Eff r) where
liftIO = lift . liftIO
{-# INLINE liftIO #-}
{-# INLINE [2] send #-}
send :: Member t r => t v -> Eff r v
send t = E (inj t) (singleK Val)
{-# RULES
"send/bind" [~3] forall t k. send t >>= k = E (inj t) (singleK k)
#-}
run :: Eff '[] w -> w
run (Val x) = x
run (E _ _) = error "extensible-effects: the impossible happened!"
{-# INLINE handle_relay #-}
handle_relay :: (a -> Eff r w) ->
(forall v. t v -> Arr r v w -> Eff r w) ->
Eff (t ': r) a -> Eff r w
handle_relay ret h m = loop m
where
loop (Val x) = ret x
loop (E u q) = case decomp u of
Right x -> h x k
Left u0 -> E u0 (singleK k)
where k = qComp q loop
{-# INLINE handle_relay_s #-}
handle_relay_s :: s ->
(s -> a -> Eff r w) ->
(forall v. s -> t v -> (s -> Arr r v w) -> Eff r w) ->
Eff (t ': r) a -> Eff r w
handle_relay_s s ret h m = loop s m
where
loop s0 (Val x) = ret s0 x
loop s0 (E u q) = case decomp u of
Right x -> h s0 x k
Left u0 -> E u0 (singleK (k s0))
where k s1 x = loop s1 $ qApp q x
{-# INLINE interpose #-}
interpose :: Member t r =>
(a -> Eff r w) -> (forall v. t v -> Arr r v w -> Eff r w) ->
Eff r a -> Eff r w
interpose ret h m = loop m
where
loop (Val x) = ret x
loop (E u q) = case prj u of
Just x -> h x k
_ -> E u (singleK k)
where k = qComp q loop
raise :: Eff r a -> Eff (e ': r) a
raise = loop
where
loop (Val x) = pure x
loop (E u q) = E (weaken u) $ qComps q loop
{-# INLINE raise #-}
newtype Lift m a = Lift (m a)
lift :: (SetMember Lift (Lift m) r) => m a -> Eff r a
lift = send . Lift
runLift :: Monad m => Eff '[Lift m] w -> m w
runLift (Val x) = return x
runLift (E u q) = case prj u of
Just (Lift m) -> m >>= runLift . qApp q
Nothing -> error "Impossible: Nothing cannot occur"