Skip to content

Instantly share code, notes, and snippets.

@kremovtort
Last active August 11, 2022 21:45
Show Gist options
  • Save kremovtort/7c154b733ed86ceeee908648912483e5 to your computer and use it in GitHub Desktop.
Save kremovtort/7c154b733ed86ceeee908648912483e5 to your computer and use it in GitHub Desktop.
fused-effects TypedAlgebra for composing effects
{-# LANGUAGE
FunctionalDependencies
, UndecidableInstances
#-}
module Control.Carrier.DependsOn where
import Control.Algebra
import Control.Applicative
import Control.Carrier.Error.Either
import Control.Effect.State
import Control.Monad.Base
import Control.Monad.Catch hiding (Handler)
import Control.Monad.IO.Class (MonadIO)
import Control.Monad.Logger (MonadLogger)
import Control.Monad.Trans.Control
import Control.Monad.Trans.State (StateT)
import Data.Kind
-- needs to define tree of effect carriers with their private dependencies
-- example:
-- (AwsClientC `DependsOn` HttpClientC :# ReaderC (HttpCtx AWS))
-- :# (HackageClientC `DependsOn` HttpClientC :# ReaderC (HttpCtx Hackage))
type CarrierKind = (Type -> Type) -> Type -> Type
type SigKind = (Type -> Type) -> Type -> Type
class
Algebra (addsSig :+: baseSig) (c m)
=> TypedAlgebra baseSig addsSig m c | c -> addsSig
instance Algebra sig m => TypedAlgebra sig (Error e) m (ErrorC e)
instance Algebra sig m => TypedAlgebra sig (State s) m (StateT s)
newtype DependsOn (t :: CarrierKind) (u :: CarrierKind) m a = DependsOnC { runDependsOnC :: t (u m) a }
deriving newtype
( Functor, Applicative, Monad, MonadIO, MonadBase b, MonadBaseControl b
, MonadThrow, MonadCatch, MonadMask, MonadLogger )
type DependsOnCons addsSigT addsSigU baseSig t u m =
( TypedAlgebra (addsSigU :+: baseSig) addsSigT (u m) t
, TypedAlgebra baseSig addsSigU m u
, Algebra baseSig m
)
instance
DependsOnCons addsSigT addsSigU baseSig t u m
=> Algebra (addsSigT :+: baseSig) (DependsOn t u m)
where
alg hdl sig ctx = case sig of
L addsSig -> DependsOnC $ alg (runDependsOnC . hdl) (L addsSig) ctx
R baseSig -> DependsOnC $ alg (runDependsOnC . hdl) (R (R baseSig)) ctx
{-# INLINE alg #-}
instance
DependsOnCons addsSigT addsSigU baseSig t u m
=> TypedAlgebra baseSig addsSigT m (DependsOn t u)
newtype ((t :: CarrierKind) :# (u :: CarrierKind)) (m :: Type -> Type) a = ComposeC { runComposeC :: t (u m) a }
deriving newtype
( Functor, Applicative, Monad, MonadFail, MonadIO, Alternative
, MonadThrow, MonadCatch, MonadMask, MonadLogger )
type ComposeCCons addsSigU addsSigT baseSig t u m =
( TypedAlgebra (addsSigU :+: baseSig) addsSigT (u m) t
, TypedAlgebra baseSig addsSigU m u
, Algebra baseSig m
)
instance
ComposeCCons addsSigU addsSigT baseSig t u m
=> Algebra ((addsSigT :+: addsSigU) :+: baseSig) ((t :# u) m)
where
alg hdl sig ctx = case sig of
L (L addsSigT) -> ComposeC $ alg (runComposeC . hdl) (L addsSigT) ctx
L (R addsSigU) -> ComposeC $ alg (runComposeC . hdl) (R (L addsSigU)) ctx
R baseSig -> ComposeC $ alg (runComposeC . hdl) (R (R baseSig)) ctx
{-# INLINE alg #-}
instance
ComposeCCons addsSigU addsSigT baseSig t u m
=> TypedAlgebra baseSig (addsSigT :+: addsSigU) m (t :# u)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment