fused-effects 0.4.0.0 → 0.5.0.0
raw patch · 33 files changed
+631/−393 lines, 33 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Control.Effect: send :: (Member effect sig, Carrier sig m) => effect m (m a) -> m a
- Control.Effect.Cull: instance GHC.Base.Functor (Control.Effect.Cull.Cull m)
- Control.Effect.Cut: instance GHC.Base.Functor (Control.Effect.Cut.Cut m)
- Control.Effect.Error: instance GHC.Base.Functor (Control.Effect.Error.Error exc m)
- Control.Effect.Fresh: instance GHC.Base.Functor (Control.Effect.Fresh.Fresh m)
- Control.Effect.Lift: instance GHC.Base.Functor sig => GHC.Base.Functor (Control.Effect.Lift.Lift sig m)
- Control.Effect.NonDet: instance GHC.Base.Functor (Control.Effect.NonDet.NonDet m)
- Control.Effect.Pure: instance Control.Effect.Carrier.Carrier Control.Effect.Pure.Pure Control.Effect.Pure.PureC
- Control.Effect.Pure: instance Control.Effect.Carrier.Effect Control.Effect.Pure.Pure
- Control.Effect.Pure: instance Control.Effect.Carrier.HFunctor Control.Effect.Pure.Pure
- Control.Effect.Random: instance GHC.Base.Functor (Control.Effect.Random.Random m)
- Control.Effect.Reader: instance GHC.Base.Functor (Control.Effect.Reader.Reader r m)
- Control.Effect.Resource: instance GHC.Base.Functor (Control.Effect.Resource.Resource m)
- Control.Effect.Resource: withResource :: MonadUnliftIO m => ResourceC m a -> m a
- Control.Effect.Resumable: instance GHC.Base.Functor (Control.Effect.Resumable.Resumable err m)
- Control.Effect.State.Internal: instance GHC.Base.Functor (Control.Effect.State.Internal.State s m)
- Control.Effect.State.Lazy: Get :: (s -> k) -> State s k
- Control.Effect.State.Lazy: Put :: s -> k -> State s k
- Control.Effect.State.Lazy: data State s (m :: * -> *) k
- Control.Effect.State.Lazy: get :: (Member (State s) sig, Carrier sig m) => m s
- Control.Effect.State.Lazy: gets :: (Member (State s) sig, Carrier sig m) => (s -> a) -> m a
- Control.Effect.State.Lazy: modify :: (Member (State s) sig, Carrier sig m) => (s -> s) -> m ()
- Control.Effect.State.Lazy: modifyLazy :: (Member (State s) sig, Carrier sig m) => (s -> s) -> m ()
- Control.Effect.State.Lazy: put :: (Member (State s) sig, Carrier sig m) => s -> m ()
- Control.Effect.State.Strict: Get :: (s -> k) -> State s k
- Control.Effect.State.Strict: Put :: s -> k -> State s k
- Control.Effect.State.Strict: data State s (m :: * -> *) k
- Control.Effect.State.Strict: get :: (Member (State s) sig, Carrier sig m) => m s
- Control.Effect.State.Strict: gets :: (Member (State s) sig, Carrier sig m) => (s -> a) -> m a
- Control.Effect.State.Strict: modify :: (Member (State s) sig, Carrier sig m) => (s -> s) -> m ()
- Control.Effect.State.Strict: modifyLazy :: (Member (State s) sig, Carrier sig m) => (s -> s) -> m ()
- Control.Effect.State.Strict: put :: (Member (State s) sig, Carrier sig m) => s -> m ()
- Control.Effect.Sum: instance (Control.Effect.Carrier.Effect l, Control.Effect.Carrier.Effect r) => Control.Effect.Carrier.Effect (l Control.Effect.Sum.:+: r)
- Control.Effect.Sum: instance (Control.Effect.Carrier.HFunctor l, Control.Effect.Carrier.HFunctor r) => Control.Effect.Carrier.HFunctor (l Control.Effect.Sum.:+: r)
- Control.Effect.Sum: send :: (Member effect sig, Carrier sig m) => effect m (m a) -> m a
- Control.Effect.Trace: instance GHC.Base.Functor (Control.Effect.Trace.Trace m)
- Control.Effect.Writer: instance GHC.Base.Functor (Control.Effect.Writer.Writer w m)
+ Control.Effect.Carrier: L :: f m k -> (:+:) f g k
+ Control.Effect.Carrier: R :: g m k -> (:+:) f g k
+ Control.Effect.Carrier: class GEffect m m' rep rep'
+ Control.Effect.Carrier: class GHFunctor m m' rep rep'
+ Control.Effect.Carrier: class Member (sub :: (* -> *) -> (* -> *)) sup
+ Control.Effect.Carrier: data ( f :+: g ) (m :: * -> *) k
+ Control.Effect.Carrier: ghandle :: (GEffect m m' rep rep', Functor f, Monad m) => f () -> (forall x. f (m x) -> m' (f x)) -> rep a -> rep' (f a)
+ Control.Effect.Carrier: ghmap :: (GHFunctor m m' rep rep', Functor m) => (forall x. m x -> m' x) -> rep a -> rep' a
+ Control.Effect.Carrier: infixr 4 :+:
+ Control.Effect.Carrier: inj :: Member sub sup => sub m a -> sup m a
+ Control.Effect.Carrier: instance (Control.Effect.Carrier.Effect f, Control.Effect.Carrier.Effect g) => Control.Effect.Carrier.Effect (f Control.Effect.Sum.:+: g)
+ Control.Effect.Carrier: instance (Control.Effect.Carrier.GEffect m m' l l', Control.Effect.Carrier.GEffect m m' r r') => Control.Effect.Carrier.GEffect m m' (l GHC.Generics.:*: r) (l' GHC.Generics.:*: r')
+ Control.Effect.Carrier: instance (Control.Effect.Carrier.GEffect m m' l l', Control.Effect.Carrier.GEffect m m' r r') => Control.Effect.Carrier.GEffect m m' (l GHC.Generics.:+: r) (l' GHC.Generics.:+: r')
+ Control.Effect.Carrier: instance (Control.Effect.Carrier.GHFunctor m m' l l', Control.Effect.Carrier.GHFunctor m m' r r') => Control.Effect.Carrier.GHFunctor m m' (l GHC.Generics.:*: r) (l' GHC.Generics.:*: r')
+ Control.Effect.Carrier: instance (Control.Effect.Carrier.GHFunctor m m' l l', Control.Effect.Carrier.GHFunctor m m' r r') => Control.Effect.Carrier.GHFunctor m m' (l GHC.Generics.:+: r) (l' GHC.Generics.:+: r')
+ Control.Effect.Carrier: instance (Control.Effect.Carrier.HFunctor f, Control.Effect.Carrier.HFunctor g) => Control.Effect.Carrier.HFunctor (f Control.Effect.Sum.:+: g)
+ Control.Effect.Carrier: instance (GHC.Base.Functor f, Control.Effect.Carrier.GEffect m m' g g') => Control.Effect.Carrier.GEffect m m' (f GHC.Generics.:.: g) (f GHC.Generics.:.: g')
+ Control.Effect.Carrier: instance (GHC.Base.Functor f, Control.Effect.Carrier.GHFunctor m m' g g') => Control.Effect.Carrier.GHFunctor m m' (f GHC.Generics.:.: g) (f GHC.Generics.:.: g')
+ Control.Effect.Carrier: instance Control.Effect.Carrier.Carrier Control.Effect.Pure.Pure Control.Effect.Pure.PureC
+ Control.Effect.Carrier: instance Control.Effect.Carrier.Effect Control.Effect.Pure.Pure
+ Control.Effect.Carrier: instance Control.Effect.Carrier.Effect f => Control.Effect.Carrier.GEffect m m' (GHC.Generics.Rec1 (f m)) (GHC.Generics.Rec1 (f m'))
+ Control.Effect.Carrier: instance Control.Effect.Carrier.GEffect m m' (GHC.Generics.K1 GHC.Generics.R c) (GHC.Generics.K1 GHC.Generics.R c)
+ Control.Effect.Carrier: instance Control.Effect.Carrier.GEffect m m' (GHC.Generics.Rec1 m) (GHC.Generics.Rec1 m')
+ Control.Effect.Carrier: instance Control.Effect.Carrier.GEffect m m' GHC.Generics.Par1 GHC.Generics.Par1
+ Control.Effect.Carrier: instance Control.Effect.Carrier.GEffect m m' GHC.Generics.U1 GHC.Generics.U1
+ Control.Effect.Carrier: instance Control.Effect.Carrier.GEffect m m' GHC.Generics.V1 GHC.Generics.V1
+ Control.Effect.Carrier: instance Control.Effect.Carrier.GEffect m m' rep rep' => Control.Effect.Carrier.GEffect m m' (GHC.Generics.M1 i c rep) (GHC.Generics.M1 i c rep')
+ Control.Effect.Carrier: instance Control.Effect.Carrier.GHFunctor m m' (GHC.Generics.K1 GHC.Generics.R c) (GHC.Generics.K1 GHC.Generics.R c)
+ Control.Effect.Carrier: instance Control.Effect.Carrier.GHFunctor m m' (GHC.Generics.Rec1 m) (GHC.Generics.Rec1 m')
+ Control.Effect.Carrier: instance Control.Effect.Carrier.GHFunctor m m' GHC.Generics.Par1 GHC.Generics.Par1
+ Control.Effect.Carrier: instance Control.Effect.Carrier.GHFunctor m m' GHC.Generics.U1 GHC.Generics.U1
+ Control.Effect.Carrier: instance Control.Effect.Carrier.GHFunctor m m' GHC.Generics.V1 GHC.Generics.V1
+ Control.Effect.Carrier: instance Control.Effect.Carrier.GHFunctor m m' rep rep' => Control.Effect.Carrier.GHFunctor m m' (GHC.Generics.M1 i c rep) (GHC.Generics.M1 i c rep')
+ Control.Effect.Carrier: instance Control.Effect.Carrier.HFunctor Control.Effect.Pure.Pure
+ Control.Effect.Carrier: instance Control.Effect.Carrier.HFunctor f => Control.Effect.Carrier.GHFunctor m m' (GHC.Generics.Rec1 (f m)) (GHC.Generics.Rec1 (f m'))
+ Control.Effect.Carrier: prj :: Member sub sup => sup m a -> Maybe (sub m a)
+ Control.Effect.Carrier: run :: PureC a -> a
+ Control.Effect.Carrier: send :: (Member effect sig, Carrier sig m) => effect m a -> m a
+ Control.Effect.Cull: class (HFunctor sig, Monad m) => Carrier sig m | m -> sig
+ Control.Effect.Cull: class Member (sub :: (* -> *) -> (* -> *)) sup
+ Control.Effect.Cull: instance Control.Monad.Fix.MonadFix m => Control.Monad.Fix.MonadFix (Control.Effect.Cull.CullC m)
+ Control.Effect.Cull: instance Control.Monad.Fix.MonadFix m => Control.Monad.Fix.MonadFix (Control.Effect.Cull.OnceC m)
+ Control.Effect.Cull: instance GHC.Base.Functor m => GHC.Base.Functor (Control.Effect.Cull.Cull m)
+ Control.Effect.Cull: run :: PureC a -> a
+ Control.Effect.Cut: class (HFunctor sig, Monad m) => Carrier sig m | m -> sig
+ Control.Effect.Cut: class Member (sub :: (* -> *) -> (* -> *)) sup
+ Control.Effect.Cut: instance Control.Monad.Fix.MonadFix m => Control.Monad.Fix.MonadFix (Control.Effect.Cut.CutC m)
+ Control.Effect.Cut: instance GHC.Base.Functor m => GHC.Base.Functor (Control.Effect.Cut.Cut m)
+ Control.Effect.Cut: run :: PureC a -> a
+ Control.Effect.Error: class (HFunctor sig, Monad m) => Carrier sig m | m -> sig
+ Control.Effect.Error: class Member (sub :: (* -> *) -> (* -> *)) sup
+ Control.Effect.Error: instance Control.Monad.Fix.MonadFix m => Control.Monad.Fix.MonadFix (Control.Effect.Error.ErrorC e m)
+ Control.Effect.Error: instance GHC.Base.Functor m => GHC.Base.Functor (Control.Effect.Error.Error exc m)
+ Control.Effect.Error: run :: PureC a -> a
+ Control.Effect.Fail: class (HFunctor sig, Monad m) => Carrier sig m | m -> sig
+ Control.Effect.Fail: class Member (sub :: (* -> *) -> (* -> *)) sup
+ Control.Effect.Fail: instance Control.Monad.Fix.MonadFix m => Control.Monad.Fix.MonadFix (Control.Effect.Fail.FailC m)
+ Control.Effect.Fail: instance GHC.Generics.Generic1 (Control.Effect.Fail.Fail m)
+ Control.Effect.Fail: run :: PureC a -> a
+ Control.Effect.Fresh: class (HFunctor sig, Monad m) => Carrier sig m | m -> sig
+ Control.Effect.Fresh: class Member (sub :: (* -> *) -> (* -> *)) sup
+ Control.Effect.Fresh: instance Control.Monad.Fix.MonadFix m => Control.Monad.Fix.MonadFix (Control.Effect.Fresh.FreshC m)
+ Control.Effect.Fresh: instance GHC.Base.Functor m => GHC.Base.Functor (Control.Effect.Fresh.Fresh m)
+ Control.Effect.Fresh: run :: PureC a -> a
+ Control.Effect.Interpose: instance (GHC.Base.Alternative m, GHC.Base.Monad m) => GHC.Base.MonadPlus (Control.Effect.Interpose.InterposeC eff m)
+ Control.Effect.Interpose: instance Control.Monad.Fail.MonadFail m => Control.Monad.Fail.MonadFail (Control.Effect.Interpose.InterposeC eff m)
+ Control.Effect.Interpose: instance Control.Monad.Fix.MonadFix m => Control.Monad.Fix.MonadFix (Control.Effect.Interpose.InterposeC eff m)
+ Control.Effect.Interpose: instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Control.Effect.Interpose.InterposeC eff m)
+ Control.Effect.Interpose: instance GHC.Base.Alternative m => GHC.Base.Alternative (Control.Effect.Interpose.InterposeC eff m)
+ Control.Effect.Interpret: instance Control.Monad.Fix.MonadFix m => Control.Monad.Fix.MonadFix (Control.Effect.Interpret.InterpretC eff m)
+ Control.Effect.Interpret: instance Control.Monad.Fix.MonadFix m => Control.Monad.Fix.MonadFix (Control.Effect.Interpret.InterpretStateC eff s m)
+ Control.Effect.Lift: class (HFunctor sig, Monad m) => Carrier sig m | m -> sig
+ Control.Effect.Lift: class Member (sub :: (* -> *) -> (* -> *)) sup
+ Control.Effect.Lift: instance (GHC.Base.Functor sig, GHC.Base.Functor m) => GHC.Base.Functor (Control.Effect.Lift.Lift sig m)
+ Control.Effect.Lift: instance Control.Monad.Fix.MonadFix m => Control.Monad.Fix.MonadFix (Control.Effect.Lift.LiftC m)
+ Control.Effect.Lift: instance GHC.Base.Functor sig => GHC.Generics.Generic1 (Control.Effect.Lift.Lift sig m)
+ Control.Effect.Lift: run :: PureC a -> a
+ Control.Effect.NonDet: class (HFunctor sig, Monad m) => Carrier sig m | m -> sig
+ Control.Effect.NonDet: class Member (sub :: (* -> *) -> (* -> *)) sup
+ Control.Effect.NonDet: instance Control.Monad.Fix.MonadFix m => Control.Monad.Fix.MonadFix (Control.Effect.NonDet.NonDetC m)
+ Control.Effect.NonDet: instance GHC.Base.Functor m => GHC.Base.Functor (Control.Effect.NonDet.NonDet m)
+ Control.Effect.NonDet: instance GHC.Generics.Generic1 (Control.Effect.NonDet.NonDet m)
+ Control.Effect.NonDet: run :: PureC a -> a
+ Control.Effect.Pure: instance Control.Monad.Fix.MonadFix Control.Effect.Pure.PureC
+ Control.Effect.Pure: instance GHC.Generics.Generic1 (Control.Effect.Pure.Pure m)
+ Control.Effect.Random: class (HFunctor sig, Monad m) => Carrier sig m | m -> sig
+ Control.Effect.Random: class Member (sub :: (* -> *) -> (* -> *)) sup
+ Control.Effect.Random: instance Control.Monad.Fix.MonadFix m => Control.Monad.Fix.MonadFix (Control.Effect.Random.RandomC g m)
+ Control.Effect.Random: instance GHC.Base.Functor m => GHC.Base.Functor (Control.Effect.Random.Random m)
+ Control.Effect.Random: run :: PureC a -> a
+ Control.Effect.Reader: class (HFunctor sig, Monad m) => Carrier sig m | m -> sig
+ Control.Effect.Reader: class Member (sub :: (* -> *) -> (* -> *)) sup
+ Control.Effect.Reader: instance Control.Monad.Fix.MonadFix m => Control.Monad.Fix.MonadFix (Control.Effect.Reader.ReaderC s m)
+ Control.Effect.Reader: instance GHC.Base.Functor m => GHC.Base.Functor (Control.Effect.Reader.Reader r m)
+ Control.Effect.Reader: run :: PureC a -> a
+ Control.Effect.Resource: instance Control.Monad.Fix.MonadFix m => Control.Monad.Fix.MonadFix (Control.Effect.Resource.ResourceC m)
+ Control.Effect.Resource: instance GHC.Base.Functor m => GHC.Base.Functor (Control.Effect.Resource.Resource m)
+ Control.Effect.Resumable: class (HFunctor sig, Monad m) => Carrier sig m | m -> sig
+ Control.Effect.Resumable: class Member (sub :: (* -> *) -> (* -> *)) sup
+ Control.Effect.Resumable: instance Control.Monad.Fix.MonadFix m => Control.Monad.Fix.MonadFix (Control.Effect.Resumable.ResumableC err m)
+ Control.Effect.Resumable: instance Control.Monad.Fix.MonadFix m => Control.Monad.Fix.MonadFix (Control.Effect.Resumable.ResumableWithC err m)
+ Control.Effect.Resumable: instance GHC.Base.Functor m => GHC.Base.Functor (Control.Effect.Resumable.Resumable err m)
+ Control.Effect.Resumable: run :: PureC a -> a
+ Control.Effect.State.Internal: class Member (sub :: (* -> *) -> (* -> *)) sup
+ Control.Effect.State.Internal: instance GHC.Base.Functor m => GHC.Base.Functor (Control.Effect.State.Internal.State s m)
+ Control.Effect.State.Internal: instance GHC.Generics.Generic1 (Control.Effect.State.Internal.State s m)
+ Control.Effect.State.Lazy: class (HFunctor sig, Monad m) => Carrier sig m | m -> sig
+ Control.Effect.State.Lazy: instance Control.Monad.Fix.MonadFix m => Control.Monad.Fix.MonadFix (Control.Effect.State.Lazy.StateC s m)
+ Control.Effect.State.Lazy: run :: PureC a -> a
+ Control.Effect.State.Strict: class (HFunctor sig, Monad m) => Carrier sig m | m -> sig
+ Control.Effect.State.Strict: instance Control.Monad.Fix.MonadFix m => Control.Monad.Fix.MonadFix (Control.Effect.State.Strict.StateC s m)
+ Control.Effect.State.Strict: run :: PureC a -> a
+ Control.Effect.Sum: instance (Data.Foldable.Foldable (f m), Data.Foldable.Foldable (g m)) => Data.Foldable.Foldable ((Control.Effect.Sum.:+:) f g m)
+ Control.Effect.Sum: instance (Data.Traversable.Traversable (f m), Data.Traversable.Traversable (g m)) => Data.Traversable.Traversable ((Control.Effect.Sum.:+:) f g m)
+ Control.Effect.Sum: instance GHC.Generics.Generic1 ((Control.Effect.Sum.:+:) f g m)
+ Control.Effect.Trace: class (HFunctor sig, Monad m) => Carrier sig m | m -> sig
+ Control.Effect.Trace: class Member (sub :: (* -> *) -> (* -> *)) sup
+ Control.Effect.Trace: instance Control.Monad.Fix.MonadFix m => Control.Monad.Fix.MonadFix (Control.Effect.Trace.TraceByIgnoringC m)
+ Control.Effect.Trace: instance Control.Monad.Fix.MonadFix m => Control.Monad.Fix.MonadFix (Control.Effect.Trace.TraceByPrintingC m)
+ Control.Effect.Trace: instance Control.Monad.Fix.MonadFix m => Control.Monad.Fix.MonadFix (Control.Effect.Trace.TraceByReturningC m)
+ Control.Effect.Trace: instance GHC.Base.Functor m => GHC.Base.Functor (Control.Effect.Trace.Trace m)
+ Control.Effect.Trace: instance GHC.Generics.Generic1 (Control.Effect.Trace.Trace m)
+ Control.Effect.Trace: run :: PureC a -> a
+ Control.Effect.Writer: class (HFunctor sig, Monad m) => Carrier sig m | m -> sig
+ Control.Effect.Writer: class Member (sub :: (* -> *) -> (* -> *)) sup
+ Control.Effect.Writer: instance Control.Monad.Fix.MonadFix m => Control.Monad.Fix.MonadFix (Control.Effect.Writer.WriterC w m)
+ Control.Effect.Writer: instance GHC.Base.Functor m => GHC.Base.Functor (Control.Effect.Writer.Writer w m)
+ Control.Effect.Writer: run :: PureC a -> a
- Control.Effect: data Lift sig (m :: * -> *) k
+ Control.Effect: data Lift sig m k
- Control.Effect: data NonDet (m :: * -> *) k
+ Control.Effect: data NonDet m k
- Control.Effect: data Resumable err (m :: * -> *) k
+ Control.Effect: data Resumable err m k
- Control.Effect: data State s (m :: * -> *) k
+ Control.Effect: data State s m k
- Control.Effect: data Trace (m :: * -> *) k
+ Control.Effect: data Trace m k
- Control.Effect.Carrier: eff :: Carrier sig m => sig m (m a) -> m a
+ Control.Effect.Carrier: eff :: Carrier sig m => sig m a -> m a
- Control.Effect.Carrier: fmap' :: (HFunctor h, Functor (h m)) => (a -> b) -> h m a -> h m b
+ Control.Effect.Carrier: fmap' :: (HFunctor h, Functor (h f)) => (a -> b) -> h f a -> h f b
- Control.Effect.Carrier: handle :: (Effect sig, Functor f, Coercible (sig m (n (f a))) (sig n (n (f a)))) => f () -> (forall x. f (m x) -> n (f x)) -> sig m (m a) -> sig n (n (f a))
+ Control.Effect.Carrier: handle :: (Effect sig, Functor f, Monad m, Generic1 (sig m), Generic1 (sig n), GEffect m n (Rep1 (sig m)) (Rep1 (sig n))) => f () -> (forall x. f (m x) -> n (f x)) -> sig m a -> sig n (f a)
- Control.Effect.Carrier: handleCoercible :: (HFunctor sig, Coercible f g) => sig f (f a) -> sig g (g a)
+ Control.Effect.Carrier: handleCoercible :: (HFunctor sig, Functor f, Coercible f g) => sig f a -> sig g a
- Control.Effect.Carrier: handlePure :: HFunctor sig => (forall x. f x -> g x) -> sig f (f a) -> sig g (g a)
+ Control.Effect.Carrier: handlePure :: (HFunctor sig, Functor f) => (forall x. f x -> g x) -> sig f a -> sig g a
- Control.Effect.Carrier: hmap :: (HFunctor h, Coercible (h m a) (h n a)) => (forall x. m x -> n x) -> h m a -> h n a
+ Control.Effect.Carrier: hmap :: (HFunctor h, Functor m, Generic1 (h m), Generic1 (h n), GHFunctor m n (Rep1 (h m)) (Rep1 (h n))) => (forall x. m x -> n x) -> h m a -> h n a
- Control.Effect.Cull: Cull :: m a -> (a -> k) -> Cull m k
+ Control.Effect.Cull: Cull :: m a -> (a -> m k) -> Cull m k
- Control.Effect.Cut: Call :: m a -> (a -> k) -> Cut m k
+ Control.Effect.Cut: Call :: m a -> (a -> m k) -> Cut m k
- Control.Effect.Error: Catch :: m b -> (exc -> m b) -> (b -> k) -> Error exc m k
+ Control.Effect.Error: Catch :: m b -> (exc -> m b) -> (b -> m k) -> Error exc m k
- Control.Effect.Fresh: Fresh :: (Int -> k) -> Fresh m k
+ Control.Effect.Fresh: Fresh :: (Int -> m k) -> Fresh m k
- Control.Effect.Fresh: Reset :: m b -> (b -> k) -> Fresh m k
+ Control.Effect.Fresh: Reset :: m b -> (b -> m k) -> Fresh m k
- Control.Effect.Interpose: runInterpose :: (forall x. eff m (m x) -> m x) -> InterposeC eff m a -> m a
+ Control.Effect.Interpose: runInterpose :: (forall x. eff m x -> m x) -> InterposeC eff m a -> m a
- Control.Effect.Interpret: runInterpret :: (forall x. eff m (m x) -> m x) -> InterpretC eff m a -> m a
+ Control.Effect.Interpret: runInterpret :: (forall x. eff m x -> m x) -> InterpretC eff m a -> m a
- Control.Effect.Interpret: runInterpretState :: (forall x. s -> eff (StateC s m) (StateC s m x) -> m (s, x)) -> s -> InterpretStateC eff s m a -> m (s, a)
+ Control.Effect.Interpret: runInterpretState :: (forall x. s -> eff (StateC s m) x -> m (s, x)) -> s -> InterpretStateC eff s m a -> m (s, a)
- Control.Effect.Lift: Lift :: sig k -> Lift sig k
+ Control.Effect.Lift: Lift :: sig (m k) -> Lift sig m k
- Control.Effect.Lift: [unLift] :: Lift sig k -> sig k
+ Control.Effect.Lift: [unLift] :: Lift sig m k -> sig (m k)
- Control.Effect.Lift: newtype Lift sig (m :: * -> *) k
+ Control.Effect.Lift: newtype Lift sig m k
- Control.Effect.NonDet: Choose :: (Bool -> k) -> NonDet k
+ Control.Effect.NonDet: Choose :: (Bool -> m k) -> NonDet m k
- Control.Effect.NonDet: Empty :: NonDet k
+ Control.Effect.NonDet: Empty :: NonDet m k
- Control.Effect.NonDet: data NonDet (m :: * -> *) k
+ Control.Effect.NonDet: data NonDet m k
- Control.Effect.Random: Interleave :: m a -> (a -> k) -> Random m k
+ Control.Effect.Random: Interleave :: m a -> (a -> m k) -> Random m k
- Control.Effect.Random: Random :: (a -> k) -> Random m k
+ Control.Effect.Random: Random :: (a -> m k) -> Random m k
- Control.Effect.Random: RandomR :: (a, a) -> (a -> k) -> Random m k
+ Control.Effect.Random: RandomR :: (a, a) -> (a -> m k) -> Random m k
- Control.Effect.Reader: Ask :: (r -> k) -> Reader r m k
+ Control.Effect.Reader: Ask :: (r -> m k) -> Reader r m k
- Control.Effect.Reader: Local :: (r -> r) -> m b -> (b -> k) -> Reader r m k
+ Control.Effect.Reader: Local :: (r -> r) -> m b -> (b -> m k) -> Reader r m k
- Control.Effect.Resource: OnError :: m resource -> (resource -> m any) -> (resource -> m output) -> (output -> k) -> Resource m k
+ Control.Effect.Resource: OnError :: m resource -> (resource -> m any) -> (resource -> m output) -> (output -> m k) -> Resource m k
- Control.Effect.Resource: Resource :: m resource -> (resource -> m any) -> (resource -> m output) -> (output -> k) -> Resource m k
+ Control.Effect.Resource: Resource :: m resource -> (resource -> m any) -> (resource -> m output) -> (output -> m k) -> Resource m k
- Control.Effect.Resource: runResource :: (forall x. m x -> IO x) -> ResourceC m a -> m a
+ Control.Effect.Resource: runResource :: MonadUnliftIO m => ResourceC m a -> m a
- Control.Effect.Resumable: Resumable :: err a -> (a -> k) -> Resumable err k
+ Control.Effect.Resumable: Resumable :: err a -> (a -> m k) -> Resumable err m k
- Control.Effect.Resumable: SomeError :: err a -> SomeError
+ Control.Effect.Resumable: SomeError :: err a -> SomeError err
- Control.Effect.Resumable: data Resumable err (m :: * -> *) k
+ Control.Effect.Resumable: data Resumable err m k
- Control.Effect.Resumable: data SomeError (err :: * -> *)
+ Control.Effect.Resumable: data SomeError err
- Control.Effect.State.Internal: Get :: (s -> k) -> State s k
+ Control.Effect.State.Internal: Get :: (s -> m k) -> State s m k
- Control.Effect.State.Internal: Put :: s -> k -> State s k
+ Control.Effect.State.Internal: Put :: s -> m k -> State s m k
- Control.Effect.State.Internal: data State s (m :: * -> *) k
+ Control.Effect.State.Internal: data State s m k
- Control.Effect.Trace: Trace :: String -> k -> Trace k
+ Control.Effect.Trace: Trace :: String -> m k -> Trace m k
- Control.Effect.Trace: [traceCont] :: Trace k -> k
+ Control.Effect.Trace: [traceCont] :: Trace m k -> m k
- Control.Effect.Trace: [traceMessage] :: Trace k -> String
+ Control.Effect.Trace: [traceMessage] :: Trace m k -> String
- Control.Effect.Trace: data Trace (m :: * -> *) k
+ Control.Effect.Trace: data Trace m k
- Control.Effect.Writer: Censor :: (w -> w) -> m a -> (a -> k) -> Writer w m k
+ Control.Effect.Writer: Censor :: (w -> w) -> m a -> (a -> m k) -> Writer w m k
- Control.Effect.Writer: Listen :: m a -> (w -> a -> k) -> Writer w m k
+ Control.Effect.Writer: Listen :: m a -> (w -> a -> m k) -> Writer w m k
- Control.Effect.Writer: Tell :: w -> k -> Writer w m k
+ Control.Effect.Writer: Tell :: w -> m k -> Writer w m k
Files
- ChangeLog.md +30/−0
- README.md +10/−9
- benchmark/Bench.hs +8/−7
- examples/Main.hs +3/−1
- examples/Parser.hs +6/−14
- examples/ReinterpretLog.hs +13/−26
- examples/Teletype.hs +11/−9
- fused-effects.cabal +15/−13
- src/Control/Effect.hs +1/−2
- src/Control/Effect/Carrier.hs +154/−36
- src/Control/Effect/Cull.hs +19/−13
- src/Control/Effect/Cut.hs +22/−12
- src/Control/Effect/Error.hs +20/−10
- src/Control/Effect/Fail.hs +14/−7
- src/Control/Effect/Fresh.hs +18/−12
- src/Control/Effect/Interpose.hs +14/−10
- src/Control/Effect/Interpret.hs +13/−13
- src/Control/Effect/Lift.hs +13/−6
- src/Control/Effect/NonDet.hs +22/−10
- src/Control/Effect/Pure.hs +11/−15
- src/Control/Effect/Random.hs +21/−15
- src/Control/Effect/Reader.hs +23/−13
- src/Control/Effect/Resource.hs +29/−18
- src/Control/Effect/Resumable.hs +31/−21
- src/Control/Effect/State/Internal.hs +17/−13
- src/Control/Effect/State/Lazy.hs +18/−14
- src/Control/Effect/State/Strict.hs +17/−13
- src/Control/Effect/Sum.hs +3/−21
- src/Control/Effect/Trace.hs +20/−12
- src/Control/Effect/Writer.hs +23/−17
- test/Control/Effect/NonDet/Spec.hs +3/−2
- test/Control/Effect/Spec.hs +6/−8
- test/Spec.hs +3/−1
ChangeLog.md view
@@ -1,3 +1,33 @@+# v0.5.0.0++- Derives `Generic1` instances for all non-existentially-quantified effect datatypes.++- Derives `Foldable` & `Traversable` instances for `:+:`.++- Defines `MonadFix` instances for all of the carriers.++- Re-exports `run`, `:+:`, and `Member` from `Control.Effect.Carrier`, reducing the number of imports needed when defining new effects.++- Re-exports `Carrier`, `Member`, and `run` from the various effect modules, reducing the number of imports needed when using existing effects.++## Backwards-incompatible changes++- Replaces `runResource` with an equivalent function that uses `MonadUnliftIO` to select the correct unlifting function (a la `withResource`, which is removed in favor of `runResource`).++- Changes the signature of `eff` from `sig m (m a) -> m a` to `sig m a -> m a`, requiring effects to hold `m k` in their continuation positions instead of merely `k`. This was done in order to improve interoperability with other presentations of higher-order syntax, e.g. `bound`; syntax used with `bound` can now be given `HFunctor` and `Carrier` instances.++ To upgrade effects used with previous versions, change any continuations from `k` to `m k`. If no existential type variables appear in the effect, you can derive `Generic1`, and thence `HFunctor` & `Effect` instances. Otherwise, implement the required instances by hand. Since continuation positions now occur in `m`, `hmap` definitions will have to apply the higher-order function to these as well.++- Adds `Functor` constraints to `hmap` and `Monad` constraints to `handle`, allowing a greater variety of instances to be defined (e.g. for recursively-nested syntax).++- Replaces the default definitions of `hmap` and `handle` with derivations based on `Generic1` instead of `Coercible`. Therefore, first-order effects wishing to derive these instances will require `Generic1` instances, presumably derived using `-XDeriveGeneric`.++- Moves `send` from `Control.Effect.Sum` to `Control.Effect.Carrier`. Likewise removes the re-export of `send` from `Control.Effect`.++- Deprecates `fmap'` in favour of `fmap`.++- Deprecates `handlePure` in favour of `hmap`.+ # v0.4.0.0 ## Backwards-incompatible changes
README.md view
@@ -1,6 +1,6 @@ # A fast, flexible, fused effect system for Haskell -[](https://travis-ci.com/fused-effects/fused-effects)+[](https://travis-ci.com/fused-effects/fused-effects) [](http://hackage.haskell.org/package/fused-effects) - [Overview][] - [Algebraic effects][]@@ -112,11 +112,11 @@ ```haskell example1 :: (Carrier sig m, Effect sig) => [a] -> m (Int, ()) example1 list = runState 0 $ do- i <- get+ i <- get @Int put (i + length list) ``` -`runState` returns a tuple of both the computed value (the `()`) and the final state (the `Int`), visible in the result of the returned computation.+`runState` returns a tuple of both the computed value (the `()`) and the final state (the `Int`), visible in the result of the returned computation. The `get` function is resolved with a visible type application, due to the fact that effects can contain more than one state type (in contrast with `mtl`'s `MonadState`, which limits the user to a single state type). Since this function returns a value in some carrier `m`, effect handlers can be chained to run multiple effects. Here, we get the list to compute the length of from a `Reader` effect: @@ -127,7 +127,7 @@ put (length (list :: String)) ``` -(Note that the type annotation on `list` is necessary to disambiguate the requested value, since otherwise all the typechecker knows is that it’s an arbitrary `Foldable`. For more information, see the [comparison to `mtl`](#comparison-to--mtl-).)+(Note that the type annotation on `list` is necessary to disambiguate the requested value, since otherwise all the typechecker knows is that it’s an arbitrary `Foldable`. For more information, see the [comparison to `mtl`](#comparison-to-mtl).) When all effects have been handled, a computation’s final value can be extracted with `run`: @@ -154,17 +154,18 @@ ### Required compiler extensions -To use effects, you'll need a relatively-uncontroversial set of extensions: `-XFlexibleContexts`, `-XFlexibleInstances`, and `-XMultiParamTypeClasses`.+To use effects, you'll typically need `-XFlexibleContexts`. -When defining your own effects, you'll need `-XTypeOperators` to declare a `Carrier` instance over (`:+:`), and `-XUndecidableInstances` to satisfy the coverage condition for this instance. You may need `-XKindSignatures` if GHC cannot correctly infer the type of your handler; see the [documentation on common errors][common] for more information about this case.+When defining your own effects, you may need `-XKindSignatures` if GHC cannot correctly infer the type of your handler; see the [documentation on common errors][common] for more information about this case. `-XDeriveGeneric` can be used with many first-order effects to derive default implementations of `HFunctor` and `Effect`. +When defining carriers, you'll need `-XTypeOperators` to declare a `Carrier` instance over (`:+:`), `-XFlexibleInstances` to loosen the conditions on the instance, `-XMultiParamTypeClasses` since `Carrier` takes two parameters, and `-XUndecidableInstances` to satisfy the coverage condition for this instance.+ [common]: https://github.com/fused-effects/fused-effects/blob/master/docs/common_errors.md -The following invocation, taken from the teletype example, should suffice for any use or construction of effects:+The following invocation, taken from the teletype example, should suffice for most use or construction of effects and carriers: ```haskell-{-# LANGUAGE DeriveFunctor, FlexibleContexts, FlexibleInstances, GeneralizedNewtypeDeriving,- KindSignatures, MultiParamTypeClasses, TypeOperators, UndecidableInstances #-}+{-# LANGUAGE DeriveFunctor, DeriveGeneric, DerivingStrategies, FlexibleContexts, FlexibleInstances, GeneralizedNewtypeDeriving, MultiParamTypeClasses, TypeOperators, UndecidableInstances #-} ``` ### Defining new effects
benchmark/Bench.hs view
@@ -1,14 +1,15 @@ {-# LANGUAGE DeriveFunctor, FlexibleContexts, FlexibleInstances, LambdaCase, MultiParamTypeClasses, RankNTypes, TypeApplications, TypeOperators, UndecidableInstances #-}-module Main where+module Main+( main+) where -import Control.Effect import Control.Effect.Carrier import Control.Effect.Interpret-import Control.Effect.Pure import Control.Effect.Writer import Control.Effect.State import Control.Monad (ap, replicateM_) import Criterion.Main+import Data.Functor.Identity import Data.Monoid (Sum(..)) main :: IO ()@@ -59,10 +60,10 @@ ] ] -tellLoop :: (Applicative m, Carrier sig m, Member (Writer (Sum Int)) sig) => Int -> m ()+tellLoop :: (Carrier sig m, Member (Writer (Sum Int)) sig) => Int -> m () tellLoop i = replicateM_ i (tell (Sum (1 :: Int))) -modLoop :: (Applicative m, Carrier sig m, Member (State (Sum Int)) sig) => Int -> m ()+modLoop :: (Carrier sig m, Member (State (Sum Int)) sig) => Int -> m () modLoop i = replicateM_ i (modify (+ (Sum (1 :: Int)))) newtype Cod m a = Cod { unCod :: forall b . (a -> m b) -> m b }@@ -78,5 +79,5 @@ instance Monad (Cod m) where Cod a >>= f = Cod (\ k -> a (runCod k . f)) -instance Carrier sig m => Carrier sig (Cod m) where- eff op = Cod (\ k -> eff (hmap (runCod pure) (fmap' (runCod k) op)))+instance (Carrier sig m, Effect sig) => Carrier sig (Cod m) where+ eff op = Cod (\ k -> eff (handle (Identity ()) (runCod (pure . Identity) . runIdentity) op) >>= k . runIdentity)
examples/Main.hs view
@@ -1,4 +1,6 @@-module Main where+module Main+( main+) where import qualified Parser import qualified ReinterpretLog
examples/Parser.hs view
@@ -1,18 +1,16 @@-{-# LANGUAGE DeriveFoldable, DeriveFunctor, DeriveTraversable, ExistentialQuantification, FlexibleContexts, FlexibleInstances, GeneralizedNewtypeDeriving, KindSignatures, MultiParamTypeClasses, StandaloneDeriving, TypeOperators, UndecidableInstances #-}+{-# LANGUAGE DeriveAnyClass, DeriveGeneric, DeriveTraversable, DerivingStrategies, ExistentialQuantification, FlexibleContexts, FlexibleInstances, GeneralizedNewtypeDeriving, MultiParamTypeClasses, StandaloneDeriving, TypeOperators, UndecidableInstances #-} module Parser ( spec ) where -import Control.Effect import Control.Effect.Carrier import Control.Effect.Cut import Control.Effect.NonDet import Control.Effect.State-import Control.Effect.Sum import Control.Monad (replicateM) import Data.Char-import Data.Coerce import Data.List (intercalate)+import GHC.Generics (Generic1) import Test.Hspec import Test.Hspec.QuickCheck import Test.QuickCheck@@ -74,15 +72,9 @@ replicateM m (vector n') -data Symbol (m :: * -> *) k = Satisfy (Char -> Bool) (Char -> k)- deriving (Functor)--instance HFunctor Symbol where- hmap _ = coerce- {-# INLINE hmap #-}--instance Effect Symbol where- handle state handler = coerce . fmap (handler . (<$ state))+data Symbol m k = Satisfy (Char -> Bool) (Char -> m k)+ deriving stock (Functor, Generic1)+ deriving anyclass (HFunctor, Effect) satisfy :: (Carrier sig m, Member Symbol sig) => (Char -> Bool) -> m Char satisfy p = send (Satisfy p pure)@@ -103,7 +95,7 @@ exhaustive _ = empty newtype ParseC m a = ParseC { runParseC :: StateC String m a }- deriving (Alternative, Applicative, Functor, Monad)+ deriving newtype (Alternative, Applicative, Functor, Monad) instance (Alternative m, Carrier sig m, Effect sig) => Carrier (Symbol :+: sig) (ParseC m) where eff (L (Satisfy p k)) = do
examples/ReinterpretLog.hs view
@@ -10,7 +10,9 @@ -- structured log messages as strings. +{-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DerivingStrategies #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-}@@ -27,17 +29,18 @@ module ReinterpretLog ( spec+ , application+ , runApplication ) where -import Control.Effect import Control.Effect.Carrier+import Control.Effect.Lift import Control.Effect.Reader-import Control.Effect.Sum import Control.Effect.Writer import Control.Monad.IO.Class (MonadIO(..))-import Data.Coerce (coerce) import Data.Function ((&)) import Data.Kind (Type)+import GHC.Generics (Generic1) import Prelude hiding (log) import Test.Hspec @@ -105,25 +108,9 @@ -- Log an 'a', then continue with 'k'. data Log (a :: Type) (m :: Type -> Type) (k :: Type)- = Log a k- deriving stock (Functor)---- Log is a "first order" effect, so the Effect and HFunctor instance are--- boilerplate. See https://github.com/fused-effects/fused-effects/issues/54-instance Effect (Log a) where- handle ::- Functor f- => f ()- -> (forall x. f (m x) -> n (f x))- -> Log a m (m b)- -> Log a n (n (f b))- handle state handler =- coerce . fmap (handler . ((<$ state)))--instance HFunctor (Log a) where- hmap :: (forall x. m x -> n x) -> Log a m k -> Log a n k- hmap _ =- coerce+ = Log a (m k)+ deriving stock (Functor, Generic1)+ deriving anyclass (HFunctor, Effect) -- Log an 'a'. log ::@@ -154,7 +141,7 @@ -- ... the 'LogStdoutC m' monad can interpret 'Log String :+: sig' effects => Carrier (Log String :+: sig) (LogStdoutC m) where - eff :: (Log String :+: sig) (LogStdoutC m) (LogStdoutC m a) -> LogStdoutC m a+ eff :: (Log String :+: sig) (LogStdoutC m) a -> LogStdoutC m a eff = \case L (Log message k) -> LogStdoutC $ do@@ -162,7 +149,7 @@ runLogStdout k R other ->- LogStdoutC (eff (handlePure runLogStdout other))+ LogStdoutC (eff (hmap runLogStdout other)) -- The 'LogStdoutC' runner. runLogStdout ::@@ -189,7 +176,7 @@ => Carrier (Log s :+: sig) (ReinterpretLogC s t m) where eff ::- (Log s :+: sig) (ReinterpretLogC s t m) (ReinterpretLogC s t m a)+ (Log s :+: sig) (ReinterpretLogC s t m) a -> ReinterpretLogC s t m a eff = \case L (Log s k) ->@@ -227,7 +214,7 @@ => Carrier (Log s :+: sig) (CollectLogMessagesC s m) where eff ::- (Log s :+: sig) (CollectLogMessagesC s m) (CollectLogMessagesC s m a)+ (Log s :+: sig) (CollectLogMessagesC s m) a -> CollectLogMessagesC s m a eff = \case L (Log s k) ->
examples/Teletype.hs view
@@ -1,16 +1,17 @@-{-# LANGUAGE DeriveAnyClass, DeriveFunctor, DerivingStrategies, FlexibleContexts, FlexibleInstances, GeneralizedNewtypeDeriving, KindSignatures, MultiParamTypeClasses, TypeOperators, UndecidableInstances #-}+{-# LANGUAGE DeriveAnyClass, DeriveFunctor, DeriveGeneric, DerivingStrategies, FlexibleContexts, FlexibleInstances, GeneralizedNewtypeDeriving, MultiParamTypeClasses, TypeOperators, UndecidableInstances #-} -module Teletype where+module Teletype+( spec+, runTeletypeIO+) where import Prelude hiding (read) -import Control.Effect import Control.Effect.Carrier import Control.Effect.State-import Control.Effect.Sum import Control.Effect.Writer import Control.Monad.IO.Class-import Data.Coerce+import GHC.Generics (Generic1) import Test.Hspec import Test.Hspec.QuickCheck @@ -25,10 +26,11 @@ prop "writes multiple things" $ \ input output1 output2 -> run (runTeletypeRet input (write output1 >> write output2)) `shouldBe` ([output1, output2], (input, ())) -data Teletype (m :: * -> *) k- = Read (String -> k)- | Write String k- deriving (Functor, HFunctor, Effect)+data Teletype m k+ = Read (String -> m k)+ | Write String (m k)+ deriving stock (Functor, Generic1)+ deriving anyclass (HFunctor, Effect) read :: (Member Teletype sig, Carrier sig m) => m String read = send (Read pure)
fused-effects.cabal view
@@ -1,9 +1,11 @@+cabal-version: 2.2+ name: fused-effects-version: 0.4.0.0+version: 0.5.0.0 synopsis: A fast, flexible, fused effect system. description: A fast, flexible, fused effect system, à la Effect Handlers in Scope, Monad Transformers and Modular Algebraic Effects: What Binds Them Together, and Fusion for Free—Efficient Algebraic Effect Handlers. homepage: https://github.com/fused-effects/fused-effects-license: BSD3+license: BSD-3-Clause license-file: LICENSE author: Nicolas Wu, Tom Schrijvers, Rob Rix, Patrick Thomson maintainer: robrix@github.com@@ -13,13 +15,19 @@ extra-source-files: README.md ChangeLog.md-cabal-version: >=1.10 tested-with: GHC == 8.2.2 , GHC == 8.4.4 , GHC == 8.6.2 +common common+ default-language: Haskell2010+ ghc-options: -Weverything -Wno-missing-local-signatures -Wno-missing-import-lists -Wno-implicit-prelude -Wno-safe -Wno-unsafe -Wno-name-shadowing -Wno-monomorphism-restriction -Wno-missed-specialisations -Wno-all-missed-specialisations+ if (impl(ghc >= 8.6))+ ghc-options: -Wno-star-is-type+ library+ import: common exposed-modules: Control.Effect , Control.Effect.Carrier , Control.Effect.Cull@@ -50,15 +58,10 @@ , random , transformers hs-source-dirs: src- default-language: Haskell2010- ghc-options: -Weverything -Wno-missing-local-signatures -Wno-missing-import-lists -Wno-implicit-prelude -Wno-safe -Wno-unsafe -Wno-name-shadowing -Wno-monomorphism-restriction -Wno-missed-specialisations -Wno-all-missed-specialisations- if (impl(ghc >= 8.4))- ghc-options: -Wno-missing-export-lists- if (impl(ghc >= 8.6))- ghc-options: -Wno-star-is-type test-suite examples+ import: common type: exitcode-stdio-1.0 main-is: Main.hs other-modules: Parser@@ -70,9 +73,9 @@ , QuickCheck >= 2.7 && < 3 , transformers hs-source-dirs: examples- default-language: Haskell2010 test-suite test+ import: common type: exitcode-stdio-1.0 main-is: Spec.hs other-modules: Control.Effect.Spec@@ -82,26 +85,25 @@ , hspec >=2.4.1 , inspection-testing >= 0.4 && <1 hs-source-dirs: test- default-language: Haskell2010 test-suite doctest+ import: common type: exitcode-stdio-1.0 main-is: Doctest.hs build-depends: base >=4.9 && <4.13 , doctest >=0.7 && <1.0 , fused-effects hs-source-dirs: test- default-language: Haskell2010 benchmark benchmark+ import: common type: exitcode-stdio-1.0 main-is: Bench.hs build-depends: base >=4.9 && <4.13 , criterion , fused-effects hs-source-dirs: benchmark- default-language: Haskell2010 ghc-options: -threaded -rtsopts "-with-rtsopts=-N -A4m -n2m"
src/Control/Effect.hs view
@@ -2,7 +2,7 @@ ( module X ) where -import Control.Effect.Carrier as X (Carrier, Effect)+import Control.Effect.Carrier as X ((:+:), Carrier, Effect, Member) import Control.Effect.Cull as X (Cull, CullC, OnceC) import Control.Effect.Cut as X (Cut, CutC) import Control.Effect.Error as X (Error, ErrorC)@@ -16,6 +16,5 @@ import Control.Effect.Resource as X (Resource, ResourceC) import Control.Effect.Resumable as X (Resumable, ResumableC, ResumableWithC) import Control.Effect.State as X (State, StateC)-import Control.Effect.Sum as X ((:+:), Member, send) import Control.Effect.Trace as X (Trace, TraceByPrintingC, TraceByIgnoringC, TraceByReturningC) import Control.Effect.Writer as X (Writer, WriterC)
src/Control/Effect/Carrier.hs view
@@ -1,79 +1,197 @@-{-# LANGUAGE DefaultSignatures, DeriveFunctor, FlexibleInstances, FunctionalDependencies, RankNTypes, UndecidableInstances #-}+{-# LANGUAGE DefaultSignatures, DeriveFunctor, EmptyCase, FlexibleContexts, FlexibleInstances, FunctionalDependencies, RankNTypes, TypeOperators, UndecidableInstances #-} module Control.Effect.Carrier ( HFunctor(..) , Effect(..) , Carrier(..)+, send , handlePure , handleCoercible+-- * Generic deriving of 'HFunctor' & 'Effect' instances.+, GHFunctor(..)+, GEffect(..)+-- * Re-exports+, Pure.run+, (Sum.:+:)(..)+, Sum.Member(..) ) where -import Data.Coerce+import qualified Control.Effect.Pure as Pure+import qualified Control.Effect.Sum as Sum+import Data.Coerce+import GHC.Generics +-- | Higher-order functors of kind @(* -> *) -> (* -> *)@ map functors to functors.+--+-- All effects must be 'HFunctor's. class HFunctor h where- -- | Functor map. This is required to be 'fmap'.- --- -- This can go away once we have quantified constraints.- fmap' :: (a -> b) -> (h m a -> h m b)- default fmap' :: Functor (h m) => (a -> b) -> (h m a -> h m b)+ -- | Apply a handler specified as a natural transformation to both higher-order and continuation positions within an 'HFunctor'.+ fmap' :: Functor (h f) => (a -> b) -> h f a -> h f b fmap' = fmap {-# INLINE fmap' #-} -- | Higher-order functor map of a natural transformation over higher-order positions within the effect.- -- A definition for 'hmap' over first-order effects can be derived automatically.- hmap :: (forall x . m x -> n x) -> (h m a -> h n a)-- default hmap :: Coercible (h m a) (h n a)- => (forall x . m x -> n x)- -> (h m a -> h n a)- hmap _ = coerce+ --+ -- A definition for 'hmap' over first-order effects can be derived automatically provided a 'Generic1' instance is available.+ hmap :: Functor m => (forall x . m x -> n x) -> (h m a -> h n a)+ default hmap :: (Functor m, Generic1 (h m), Generic1 (h n), GHFunctor m n (Rep1 (h m)) (Rep1 (h n))) => (forall x . m x -> n x) -> (h m a -> h n a)+ hmap f = to1 . ghmap f . from1 {-# INLINE hmap #-} +{-# DEPRECATED fmap' "fmap' has been subsumed by fmap." #-} +instance HFunctor Pure.Pure+instance (HFunctor f, HFunctor g) => HFunctor (f Sum.:+: g)++ -- | The class of effect types, which must: -- -- 1. Be functorial in their last two arguments, and -- 2. Support threading effects in higher-order positions through using the carrier’s suspended state. ----- All first-order effects (those without recursive occurrences of @m@) admit a default definition--- of 'handle'. The @-XDeriveAnyClass@ extension allows derivation of both 'HFunctor' and 'Effect':------ @--- data State s (m :: * -> *) k--- = Get (s -> k)--- | Put s k--- deriving (Functor, HFunctor, Effect)--- @+-- All first-order effects (those without existential occurrences of @m@) admit a default definition of 'handle' provided a 'Generic1' instance is available for the effect. class HFunctor sig => Effect sig where -- | Handle any effects in a signature by threading the carrier’s state all the way through to the continuation.- handle :: Functor f+ handle :: (Functor f, Monad m) => f () -> (forall x . f (m x) -> n (f x))- -> sig m (m a)- -> sig n (n (f a))-- default handle :: (Functor f, Coercible (sig m (n (f a))) (sig n (n (f a))))+ -> sig m a+ -> sig n (f a)+ default handle :: (Functor f, Monad m, Generic1 (sig m), Generic1 (sig n), GEffect m n (Rep1 (sig m)) (Rep1 (sig n))) => f () -> (forall x . f (m x) -> n (f x))- -> sig m (m a)- -> sig n (n (f a))- handle state handler = coerce . fmap' (handler . (<$ state))+ -> sig m a+ -> sig n (f a)+ handle state handler = to1 . ghandle state handler . from1 {-# INLINE handle #-} +instance Effect Pure.Pure+instance (Effect f, Effect g) => Effect (f Sum.:+: g) -- | The class of carriers (results) for algebras (effect handlers) over signatures (effects), whose actions are given by the 'eff' method. class (HFunctor sig, Monad m) => Carrier sig m | m -> sig where -- | Construct a value in the carrier for an effect signature (typically a sum of a handled effect and any remaining effects).- eff :: sig m (m a) -> m a+ eff :: sig m a -> m a ++instance Carrier Pure.Pure Pure.PureC where+ eff v = case v of {}+ {-# INLINE eff #-}+++-- | Construct a request for an effect to be interpreted by some handler later on.+send :: (Sum.Member effect sig, Carrier sig m) => effect m a -> m a+send = eff . Sum.inj+{-# INLINE send #-}++ -- | Apply a handler specified as a natural transformation to both higher-order and continuation positions within an 'HFunctor'.-handlePure :: HFunctor sig => (forall x . f x -> g x) -> sig f (f a) -> sig g (g a)-handlePure handler = hmap handler . fmap' handler+handlePure :: (HFunctor sig, Functor f) => (forall x . f x -> g x) -> sig f a -> sig g a+handlePure = hmap {-# INLINE handlePure #-}+{-# DEPRECATED handlePure "handlePure has been subsumed by hmap." #-} -- | Thread a 'Coercible' carrier through an 'HFunctor'. -- -- This is applicable whenever @f@ is 'Coercible' to @g@, e.g. simple @newtype@s.-handleCoercible :: (HFunctor sig, Coercible f g) => sig f (f a) -> sig g (g a)-handleCoercible = handlePure coerce+handleCoercible :: (HFunctor sig, Functor f, Coercible f g) => sig f a -> sig g a+handleCoercible = hmap coerce {-# INLINE handleCoercible #-}+++-- | Generic implementation of 'HFunctor'.+class GHFunctor m m' rep rep' where+ -- | Generic implementation of 'hmap'.+ ghmap :: Functor m => (forall x . m x -> m' x) -> (rep a -> rep' a)++instance GHFunctor m m' rep rep' => GHFunctor m m' (M1 i c rep) (M1 i c rep') where+ ghmap f = M1 . ghmap f . unM1+ {-# INLINE ghmap #-}++instance (GHFunctor m m' l l', GHFunctor m m' r r') => GHFunctor m m' (l :+: r) (l' :+: r') where+ ghmap f (L1 l) = L1 (ghmap f l)+ ghmap f (R1 r) = R1 (ghmap f r)+ {-# INLINE ghmap #-}++instance (GHFunctor m m' l l', GHFunctor m m' r r') => GHFunctor m m' (l :*: r) (l' :*: r') where+ ghmap f (l :*: r) = ghmap f l :*: ghmap f r+ {-# INLINE ghmap #-}++instance GHFunctor m m' V1 V1 where+ ghmap _ v = case v of {}+ {-# INLINE ghmap #-}++instance GHFunctor m m' U1 U1 where+ ghmap _ = id+ {-# INLINE ghmap #-}++instance GHFunctor m m' (K1 R c) (K1 R c) where+ ghmap _ = coerce+ {-# INLINE ghmap #-}++instance GHFunctor m m' Par1 Par1 where+ ghmap _ = coerce+ {-# INLINE ghmap #-}++instance (Functor f, GHFunctor m m' g g') => GHFunctor m m' (f :.: g) (f :.: g') where+ ghmap f = Comp1 . fmap (ghmap f) . unComp1+ {-# INLINE ghmap #-}++instance GHFunctor m m' (Rec1 m) (Rec1 m') where+ ghmap f = Rec1 . f . unRec1+ {-# INLINE ghmap #-}++instance HFunctor f => GHFunctor m m' (Rec1 (f m)) (Rec1 (f m')) where+ ghmap f = Rec1 . hmap f . unRec1+ {-# INLINE ghmap #-}+++-- | Generic implementation of 'Effect'.+class GEffect m m' rep rep' where+ -- | Generic implementation of 'handle'.+ ghandle :: (Functor f, Monad m)+ => f ()+ -> (forall x . f (m x) -> m' (f x))+ -> rep a+ -> rep' (f a)++instance GEffect m m' rep rep' => GEffect m m' (M1 i c rep) (M1 i c rep') where+ ghandle state handler = M1 . ghandle state handler . unM1+ {-# INLINE ghandle #-}++instance (GEffect m m' l l', GEffect m m' r r') => GEffect m m' (l :+: r) (l' :+: r') where+ ghandle state handler (L1 l) = L1 (ghandle state handler l)+ ghandle state handler (R1 r) = R1 (ghandle state handler r)+ {-# INLINE ghandle #-}++instance (GEffect m m' l l', GEffect m m' r r') => GEffect m m' (l :*: r) (l' :*: r') where+ ghandle state handler (l :*: r) = ghandle state handler l :*: ghandle state handler r+ {-# INLINE ghandle #-}++instance GEffect m m' V1 V1 where+ ghandle _ _ v = case v of {}+ {-# INLINE ghandle #-}++instance GEffect m m' U1 U1 where+ ghandle _ _ = coerce+ {-# INLINE ghandle #-}++instance GEffect m m' (K1 R c) (K1 R c) where+ ghandle _ _ = coerce+ {-# INLINE ghandle #-}++instance GEffect m m' Par1 Par1 where+ ghandle state _ = Par1 . (<$ state) . unPar1+ {-# INLINE ghandle #-}++instance (Functor f, GEffect m m' g g') => GEffect m m' (f :.: g) (f :.: g') where+ ghandle state handler = Comp1 . fmap (ghandle state handler) . unComp1+ {-# INLINE ghandle #-}++instance GEffect m m' (Rec1 m) (Rec1 m') where+ ghandle state handler = Rec1 . handler . (<$ state) . unRec1+ {-# INLINE ghandle #-}++instance Effect f => GEffect m m' (Rec1 (f m)) (Rec1 (f m')) where+ ghandle state handler = Rec1 . handle state handler . unRec1+ {-# INLINE ghandle #-}
src/Control/Effect/Cull.hs view
@@ -1,32 +1,38 @@ {-# LANGUAGE DeriveFunctor, ExistentialQuantification, FlexibleContexts, FlexibleInstances, GeneralizedNewtypeDeriving, LambdaCase, MultiParamTypeClasses, StandaloneDeriving, TypeOperators, UndecidableInstances #-} module Control.Effect.Cull-( Cull(..)+( -- * Cull effect+ Cull(..) , cull+ -- * Cull carriers , runCull , CullC(..) , runNonDetOnce , OnceC(..)+-- * Re-exports+, Carrier+, Member+, run ) where import Control.Applicative (Alternative(..)) import Control.Effect.Carrier import Control.Effect.NonDet import Control.Effect.Reader-import Control.Effect.Sum import Control.Monad (MonadPlus(..)) import Control.Monad.Fail+import Control.Monad.Fix import Control.Monad.IO.Class import Control.Monad.Trans.Class import Prelude hiding (fail) -- | 'Cull' effects are used with 'NonDet' to provide control over branching. data Cull m k- = forall a . Cull (m a) (a -> k)+ = forall a . Cull (m a) (a -> m k) -deriving instance Functor (Cull m)+deriving instance Functor m => Functor (Cull m) instance HFunctor Cull where- hmap f (Cull m k) = Cull (f m) k+ hmap f (Cull m k) = Cull (f m) (f . k) {-# INLINE hmap #-} instance Effect Cull where@@ -35,21 +41,21 @@ -- | Cull nondeterminism in the argument, returning at most one result. ----- prop> run (runNonDet (runCull (cull (pure a <|> pure b)))) == [a]--- prop> run (runNonDet (runCull (cull (pure a <|> pure b) <|> pure c))) == [a, c]--- prop> run (runNonDet (runCull (cull (asum (map pure (repeat a)))))) == [a]+-- prop> run (runNonDet (runCull (cull (pure a <|> pure b)))) === [a]+-- prop> run (runNonDet (runCull (cull (pure a <|> pure b) <|> pure c))) === [a, c]+-- prop> run (runNonDet (runCull (cull (asum (map pure (repeat a)))))) === [a] cull :: (Carrier sig m, Member Cull sig) => m a -> m a cull m = send (Cull m pure) -- | Run a 'Cull' effect. Branches outside of any 'cull' block will not be pruned. ----- prop> run (runNonDet (runCull (pure a <|> pure b))) == [a, b]+-- prop> run (runNonDet (runCull (pure a <|> pure b))) === [a, b] runCull :: Alternative m => CullC m a -> m a runCull (CullC m) = runNonDetC (runReader False m) ((<|>) . pure) empty newtype CullC m a = CullC { runCullC :: ReaderC Bool (NonDetC m) a }- deriving (Applicative, Functor, Monad, MonadFail, MonadIO)+ deriving (Applicative, Functor, Monad, MonadFail, MonadFix, MonadIO) instance Alternative (CullC m) where empty = CullC empty@@ -78,13 +84,13 @@ -- -- Unlike 'runNonDet', this will terminate immediately upon finding a solution. ----- prop> run (runNonDetOnce (asum (map pure (repeat a)))) == [a]--- prop> run (runNonDetOnce (asum (map pure (repeat a)))) == Just a+-- prop> run (runNonDetOnce (asum (map pure (repeat a)))) === [a]+-- prop> run (runNonDetOnce (asum (map pure (repeat a)))) === Just a runNonDetOnce :: (Alternative f, Carrier sig m, Effect sig) => OnceC m a -> m (f a) runNonDetOnce = runNonDet . runCull . cull . runOnceC newtype OnceC m a = OnceC { runOnceC :: CullC (NonDetC m) a }- deriving (Alternative, Applicative, Functor, Monad, MonadFail, MonadIO, MonadPlus)+ deriving (Alternative, Applicative, Functor, Monad, MonadFail, MonadFix, MonadIO, MonadPlus) instance (Carrier sig m, Effect sig) => Carrier (NonDet :+: sig) (OnceC m) where eff = OnceC . eff . R . R . handleCoercible
src/Control/Effect/Cut.hs view
@@ -1,20 +1,26 @@ {-# LANGUAGE DeriveFunctor, ExistentialQuantification, FlexibleContexts, FlexibleInstances, GeneralizedNewtypeDeriving, LambdaCase, MultiParamTypeClasses, RankNTypes, StandaloneDeriving, TypeOperators, UndecidableInstances #-} module Control.Effect.Cut-( Cut(..)+( -- * Cut effect+ Cut(..) , cutfail , call , cut+ -- * Cut carrier , runCut , runCutAll , CutC(..)+-- * Re-exports+, Carrier+, Member+, run ) where import Control.Applicative (Alternative(..)) import Control.Effect.Carrier import Control.Effect.NonDet-import Control.Effect.Sum import Control.Monad (MonadPlus(..)) import Control.Monad.Fail+import Control.Monad.Fix import Control.Monad.IO.Class import Control.Monad.Trans.Class import Prelude hiding (fail)@@ -22,13 +28,13 @@ -- | 'Cut' effects are used with 'NonDet' to provide control over backtracking. data Cut m k = Cutfail- | forall a . Call (m a) (a -> k)+ | forall a . Call (m a) (a -> m k) -deriving instance Functor (Cut m)+deriving instance Functor m => Functor (Cut m) instance HFunctor Cut where hmap _ Cutfail = Cutfail- hmap f (Call m k) = Call (f m) k+ hmap f (Call m k) = Call (f m) (f . k) {-# INLINE hmap #-} instance Effect Cut where@@ -40,24 +46,24 @@ -- -- Contrast with 'empty', which fails the current branch but allows backtracking. ----- prop> run (runNonDet (runCut (cutfail <|> pure a))) == []--- prop> run (runNonDet (runCut (pure a <|> cutfail))) == [a]+-- prop> run (runNonDet (runCut (cutfail <|> pure a))) === []+-- prop> run (runNonDet (runCut (pure a <|> cutfail))) === [a] cutfail :: (Carrier sig m, Member Cut sig) => m a cutfail = send Cutfail {-# INLINE cutfail #-} -- | Delimit the effect of 'cutfail's, allowing backtracking to resume. ----- prop> run (runNonDet (runCut (call (cutfail <|> pure a) <|> pure b))) == [b]+-- prop> run (runNonDet (runCut (call (cutfail <|> pure a) <|> pure b))) === [b] call :: (Carrier sig m, Member Cut sig) => m a -> m a call m = send (Call m pure) {-# INLINE call #-} -- | Commit to the current branch, preventing backtracking within the nearest enclosing 'call' (if any) on failure. ----- prop> run (runNonDet (runCut (pure a <|> cut *> pure b))) == [a, b]--- prop> run (runNonDet (runCut (cut *> pure a <|> pure b))) == [a]--- prop> run (runNonDet (runCut (cut *> empty <|> pure a))) == []+-- prop> run (runNonDet (runCut (pure a <|> cut *> pure b))) === [a, b]+-- prop> run (runNonDet (runCut (cut *> pure a <|> pure b))) === [a]+-- prop> run (runNonDet (runCut (cut *> empty <|> pure a))) === [] cut :: (Alternative m, Carrier sig m, Member Cut sig) => m () cut = pure () <|> cutfail {-# INLINE cut #-}@@ -65,7 +71,7 @@ -- | Run a 'Cut' effect within an underlying 'Alternative' instance (typically another 'Carrier' for a 'NonDet' effect). ----- prop> run (runNonDetOnce (runCut (pure a))) == Just a+-- prop> run (runNonDetOnce (runCut (pure a))) === Just a runCut :: Alternative m => CutC m a -> m a runCut m = runCutC m ((<|>) . pure) empty empty @@ -100,6 +106,10 @@ instance MonadFail m => MonadFail (CutC m) where fail s = CutC (\ _ _ _ -> fail s) {-# INLINE fail #-}++instance MonadFix m => MonadFix (CutC m) where+ mfix f = CutC (\ cons nil _ -> mfix (\ a -> runCutC (f (head a)) (fmap . (:)) (pure []) (pure [])) >>= foldr cons nil)+ {-# INLINE mfix #-} instance MonadIO m => MonadIO (CutC m) where liftIO io = CutC (\ cons nil _ -> liftIO io >>= flip cons nil)
src/Control/Effect/Error.hs view
@@ -1,30 +1,36 @@ {-# LANGUAGE DeriveFunctor, ExistentialQuantification, FlexibleContexts, FlexibleInstances, MultiParamTypeClasses, StandaloneDeriving, TypeOperators, UndecidableInstances #-} module Control.Effect.Error-( Error(..)+( -- * Error effect+ Error(..) , throwError , catchError+ -- * Error carrier , runError , ErrorC(..)+ -- * Re-exports+, Carrier+, Member+, run ) where import Control.Applicative (Alternative(..), liftA2) import Control.Effect.Carrier-import Control.Effect.Sum import Control.Monad (MonadPlus(..), (<=<)) import Control.Monad.Fail+import Control.Monad.Fix import Control.Monad.IO.Class import Control.Monad.Trans.Class import Prelude hiding (fail) data Error exc m k = Throw exc- | forall b . Catch (m b) (exc -> m b) (b -> k)+ | forall b . Catch (m b) (exc -> m b) (b -> m k) -deriving instance Functor (Error exc m)+deriving instance Functor m => Functor (Error exc m) instance HFunctor (Error exc) where hmap _ (Throw exc) = Throw exc- hmap f (Catch m h k) = Catch (f m) (f . h) k+ hmap f (Catch m h k) = Catch (f m) (f . h) (f . k) instance Effect (Error exc) where handle _ _ (Throw exc) = Throw exc@@ -32,7 +38,7 @@ -- | Throw an error, escaping the current computation up to the nearest 'catchError' (if any). ----- prop> run (runError (throwError a)) == Left @Int @Int a+-- prop> run (runError (throwError a)) === Left @Int @Int a throwError :: (Member (Error exc) sig, Carrier sig m) => exc -> m a throwError = send . Throw @@ -44,16 +50,16 @@ -- consider if 'Control.Effect.Resource' fits your use case; if not, use 'liftIO' with -- 'Control.Exception.try' or use 'Control.Exception.Catch' from outside the effect invocation. ----- prop> run (runError (pure a `catchError` pure)) == Right a--- prop> run (runError (throwError a `catchError` pure)) == Right @Int @Int a--- prop> run (runError (throwError a `catchError` (throwError @Int))) == Left @Int @Int a+-- prop> run (runError (pure a `catchError` pure)) === Right a+-- prop> run (runError (throwError a `catchError` pure)) === Right @Int @Int a+-- prop> run (runError (throwError a `catchError` (throwError @Int))) === Left @Int @Int a catchError :: (Member (Error exc) sig, Carrier sig m) => m a -> (exc -> m a) -> m a catchError m h = send (Catch m h pure) -- | Run an 'Error' effect, returning uncaught errors in 'Left' and successful computations’ values in 'Right'. ----- prop> run (runError (pure a)) == Right @Int @Int a+-- prop> run (runError (pure a)) === Right @Int @Int a runError :: ErrorC exc m a -> m (Either exc a) runError = runErrorC @@ -75,6 +81,10 @@ instance Monad m => Monad (ErrorC e m) where ErrorC a >>= f = ErrorC (a >>= either (pure . Left) (runError . f)) {-# INLINE (>>=) #-}++instance MonadFix m => MonadFix (ErrorC e m) where+ mfix f = ErrorC (mfix (runError . either (error "mfix (ErrorC): function returned failure") f))+ {-# INLINE mfix #-} instance MonadIO m => MonadIO (ErrorC e m) where liftIO io = ErrorC (Right <$> liftIO io)
src/Control/Effect/Fail.hs view
@@ -1,33 +1,40 @@-{-# LANGUAGE DeriveAnyClass, DeriveFunctor, DerivingStrategies, FlexibleInstances, GeneralizedNewtypeDeriving, KindSignatures, MultiParamTypeClasses, TypeOperators, UndecidableInstances #-}+{-# LANGUAGE DeriveAnyClass, DeriveFunctor, DeriveGeneric, DerivingStrategies, FlexibleInstances, GeneralizedNewtypeDeriving, KindSignatures, MultiParamTypeClasses, TypeOperators, UndecidableInstances #-} module Control.Effect.Fail-( Fail(..)-, MonadFail(..)+( -- * Fail effect+ Fail(..)+ -- * Fail carrier , runFail , FailC(..)+ -- * Re-exports+, Carrier+, Member+, MonadFail(..)+, run ) where import Control.Applicative (Alternative(..)) import Control.Effect.Carrier import Control.Effect.Error-import Control.Effect.Sum import Control.Monad (MonadPlus(..)) import Control.Monad.Fail+import Control.Monad.Fix import Control.Monad.IO.Class import Control.Monad.Trans.Class+import GHC.Generics (Generic1) import Prelude hiding (fail) newtype Fail (m :: * -> *) k = Fail String- deriving stock Functor+ deriving stock (Functor, Generic1) deriving anyclass (HFunctor, Effect) -- | Run a 'Fail' effect, returning failure messages in 'Left' and successful computations’ results in 'Right'. ----- prop> run (runFail (pure a)) == Right a+-- prop> run (runFail (pure a)) === Right a runFail :: FailC m a -> m (Either String a) runFail = runError . runFailC newtype FailC m a = FailC { runFailC :: ErrorC String m a }- deriving newtype (Alternative, Applicative, Functor, Monad, MonadIO, MonadPlus, MonadTrans)+ deriving newtype (Alternative, Applicative, Functor, Monad, MonadFix, MonadIO, MonadPlus, MonadTrans) instance (Carrier sig m, Effect sig) => MonadFail (FailC m) where fail s = FailC (throwError s)
src/Control/Effect/Fresh.hs view
@@ -1,30 +1,36 @@ {-# LANGUAGE DeriveFunctor, ExistentialQuantification, FlexibleContexts, FlexibleInstances, GeneralizedNewtypeDeriving, MultiParamTypeClasses, StandaloneDeriving, TypeOperators, UndecidableInstances #-} module Control.Effect.Fresh-( Fresh(..)+( -- * Fresh effect+ Fresh(..) , fresh , resetFresh+ -- * Fresh carrier , runFresh , FreshC(..)+ -- * Re-exports+, Carrier+, Member+, run ) where import Control.Applicative (Alternative(..)) import Control.Effect.Carrier import Control.Effect.State-import Control.Effect.Sum import Control.Monad (MonadPlus(..)) import Control.Monad.Fail+import Control.Monad.Fix import Control.Monad.IO.Class import Control.Monad.Trans.Class data Fresh m k- = Fresh (Int -> k)- | forall b . Reset (m b) (b -> k)+ = Fresh (Int -> m k)+ | forall b . Reset (m b) (b -> m k) -deriving instance Functor (Fresh m)+deriving instance Functor m => Functor (Fresh m) instance HFunctor Fresh where- hmap _ (Fresh k) = Fresh k- hmap f (Reset m k) = Reset (f m) k+ hmap f (Fresh k) = Fresh (f . k)+ hmap f (Reset m k) = Reset (f m) (f . k) instance Effect Fresh where handle state handler (Fresh k) = Fresh (handler . (<$ state) . k)@@ -32,26 +38,26 @@ -- | Produce a fresh (i.e. unique) 'Int'. ----- prop> run (runFresh (replicateM n fresh)) == nub (run (runFresh (replicateM n fresh)))+-- prop> run (runFresh (replicateM n fresh)) === nub (run (runFresh (replicateM n fresh))) fresh :: (Member Fresh sig, Carrier sig m) => m Int fresh = send (Fresh pure) -- | Reset the fresh counter after running a computation. ----- prop> run (runFresh (resetFresh (replicateM m fresh) *> replicateM n fresh)) == run (runFresh (replicateM n fresh))+-- prop> run (runFresh (resetFresh (replicateM m fresh) *> replicateM n fresh)) === run (runFresh (replicateM n fresh)) resetFresh :: (Member Fresh sig, Carrier sig m) => m a -> m a resetFresh m = send (Reset m pure) -- | Run a 'Fresh' effect counting up from 0. ----- prop> run (runFresh (replicateM n fresh)) == [0..pred n]--- prop> run (runFresh (replicateM n fresh *> pure b)) == b+-- prop> run (runFresh (replicateM n fresh)) === [0..pred n]+-- prop> run (runFresh (replicateM n fresh *> pure b)) === b runFresh :: Functor m => FreshC m a -> m a runFresh = evalState 0 . runFreshC newtype FreshC m a = FreshC { runFreshC :: StateC Int m a }- deriving (Alternative, Applicative, Functor, Monad, MonadFail, MonadIO, MonadPlus, MonadTrans)+ deriving (Alternative, Applicative, Functor, Monad, MonadFail, MonadFix, MonadIO, MonadPlus, MonadTrans) instance (Carrier sig m, Effect sig) => Carrier (Fresh :+: sig) (FreshC m) where eff (L (Fresh k)) = FreshC $ do
src/Control/Effect/Interpose.hs view
@@ -10,9 +10,13 @@ , runInterpose ) where +import Control.Applicative import Control.Effect.Carrier import Control.Effect.Reader-import Control.Effect.Sum+import Control.Monad (MonadPlus (..))+import Control.Monad.Fail+import Control.Monad.Fix+import Control.Monad.IO.Class import Control.Monad.Trans.Class -- | 'runInterpose' takes a handler for a given effect (such as 'State' or 'Reader')@@ -21,28 +25,28 @@ -- the intercepted effect, and you can pass the effect on to the original handler -- using 'send'. ----- prop> run . evalState @Int a . runInterpose @(State Int) (\op -> modify @Int (+b) *> send op) $ modify @Int (+b) == a + b + b+-- prop> run . evalState @Int a . runInterpose @(State Int) (\op -> modify @Int (+b) *> send op) $ modify @Int (+b) === a + b + b ---runInterpose :: (forall x . eff m (m x) -> m x) -> InterposeC eff m a -> m a+runInterpose :: (forall x . eff m x -> m x) -> InterposeC eff m a -> m a runInterpose handler = runReader (Handler handler) . runInterposeC newtype InterposeC eff m a = InterposeC { runInterposeC :: ReaderC (Handler eff m) m a }- deriving (Applicative, Functor, Monad)+ deriving (Alternative, Applicative, Functor, Monad, MonadFail, MonadFix, MonadIO, MonadPlus) instance MonadTrans (InterposeC eff) where lift = InterposeC . lift -newtype Handler eff m = Handler (forall x . eff m (m x) -> m x)+newtype Handler eff m = Handler (forall x . eff m x -> m x) -runHandler :: HFunctor eff => Handler eff m -> eff (ReaderC (Handler eff m) m) (ReaderC (Handler eff m) m a) -> m a-runHandler h@(Handler handler) = handler . handlePure (runReader h)+runHandler :: (HFunctor eff, Functor m) => Handler eff m -> eff (ReaderC (Handler eff m) m) a -> m a+runHandler h@(Handler handler) = handler . hmap (runReader h) instance (HFunctor eff, Carrier sig m, Member eff sig) => Carrier sig (InterposeC eff m) where- eff (op :: sig (InterposeC eff m) (InterposeC eff m a))- | Just (op' :: eff (InterposeC eff m) (InterposeC eff m a)) <- prj op = do+ eff (op :: sig (InterposeC eff m) a)+ | Just (op' :: eff (InterposeC eff m) a) <- prj op = do handler <- InterposeC ask lift (runHandler handler (handleCoercible op'))- | otherwise = InterposeC (ReaderC (\ handler -> eff (handlePure (runReader handler . runInterposeC) op)))+ | otherwise = InterposeC (ReaderC (\ handler -> eff (hmap (runReader handler . runInterposeC) op))) -- $setup -- >>> :seti -XFlexibleContexts
src/Control/Effect/Interpret.hs view
@@ -10,9 +10,9 @@ import Control.Effect.Carrier import Control.Effect.Reader import Control.Effect.State-import Control.Effect.Sum import Control.Monad (MonadPlus(..)) import Control.Monad.Fail+import Control.Monad.Fix import Control.Monad.IO.Class import Control.Monad.Trans.Class @@ -22,21 +22,21 @@ -- -- At time of writing, a simple passthrough use of 'runInterpret' to handle a 'State' effect is about five times slower than using 'StateC' directly. ----- prop> run (runInterpret (\ op -> case op of { Get k -> k a ; Put _ k -> k }) get) == a-runInterpret :: (forall x . eff m (m x) -> m x) -> InterpretC eff m a -> m a+-- prop> run (runInterpret (\ op -> case op of { Get k -> k a ; Put _ k -> k }) get) === a+runInterpret :: (forall x . eff m x -> m x) -> InterpretC eff m a -> m a runInterpret handler = runReader (Handler handler) . runInterpretC newtype InterpretC eff m a = InterpretC { runInterpretC :: ReaderC (Handler eff m) m a }- deriving (Alternative, Applicative, Functor, Monad, MonadFail, MonadIO, MonadPlus)+ deriving (Alternative, Applicative, Functor, Monad, MonadFail, MonadFix, MonadIO, MonadPlus) instance MonadTrans (InterpretC eff) where lift = InterpretC . lift {-# INLINE lift #-} -newtype Handler eff m = Handler (forall x . eff m (m x) -> m x)+newtype Handler eff m = Handler (forall x . eff m x -> m x) -runHandler :: HFunctor eff => Handler eff m -> eff (InterpretC eff m) (InterpretC eff m a) -> m a-runHandler h@(Handler handler) = handler . handlePure (runReader h . runInterpretC)+runHandler :: (HFunctor eff, Functor m) => Handler eff m -> eff (InterpretC eff m) a -> m a+runHandler h@(Handler handler) = handler . hmap (runReader h . runInterpretC) instance (HFunctor eff, Carrier sig m) => Carrier (eff :+: sig) (InterpretC eff m) where eff (L op) = do@@ -52,21 +52,21 @@ -- -- At time of writing, a simple use of 'runInterpretState' to handle a 'State' effect is about four times slower than using 'StateC' directly. ----- prop> run (runInterpretState (\ s op -> case op of { Get k -> runState s (k s) ; Put s' k -> runState s' k }) a get) == a-runInterpretState :: (forall x . s -> eff (StateC s m) (StateC s m x) -> m (s, x)) -> s -> InterpretStateC eff s m a -> m (s, a)+-- prop> run (runInterpretState (\ s op -> case op of { Get k -> runState s (k s) ; Put s' k -> runState s' k }) a get) === a+runInterpretState :: (forall x . s -> eff (StateC s m) x -> m (s, x)) -> s -> InterpretStateC eff s m a -> m (s, a) runInterpretState handler state = runState state . runReader (HandlerState (\ eff -> StateC (\ s -> handler s eff))) . runInterpretStateC newtype InterpretStateC eff s m a = InterpretStateC { runInterpretStateC :: ReaderC (HandlerState eff s m) (StateC s m) a }- deriving (Alternative, Applicative, Functor, Monad, MonadFail, MonadIO, MonadPlus)+ deriving (Alternative, Applicative, Functor, Monad, MonadFail, MonadFix, MonadIO, MonadPlus) instance MonadTrans (InterpretStateC eff s) where lift = InterpretStateC . lift . lift {-# INLINE lift #-} -newtype HandlerState eff s m = HandlerState (forall x . eff (StateC s m) (StateC s m x) -> StateC s m x)+newtype HandlerState eff s m = HandlerState (forall x . eff (StateC s m) x -> StateC s m x) -runHandlerState :: HFunctor eff => HandlerState eff s m -> eff (InterpretStateC eff s m) (InterpretStateC eff s m a) -> StateC s m a-runHandlerState h@(HandlerState handler) = handler . handlePure (runReader h . runInterpretStateC)+runHandlerState :: (HFunctor eff, Functor m) => HandlerState eff s m -> eff (InterpretStateC eff s m) a -> StateC s m a+runHandlerState h@(HandlerState handler) = handler . hmap (runReader h . runInterpretStateC) instance (HFunctor eff, Carrier sig m, Effect sig) => Carrier (eff :+: sig) (InterpretStateC eff s m) where eff (L op) = do
src/Control/Effect/Lift.hs view
@@ -1,22 +1,29 @@-{-# LANGUAGE DeriveAnyClass, DeriveFunctor, DerivingStrategies, FlexibleContexts, FlexibleInstances, GeneralizedNewtypeDeriving, KindSignatures, MultiParamTypeClasses #-}+{-# LANGUAGE DeriveAnyClass, DeriveFunctor, DeriveGeneric, DerivingStrategies, FlexibleContexts, FlexibleInstances, GeneralizedNewtypeDeriving, MultiParamTypeClasses #-} module Control.Effect.Lift-( Lift(..)+( -- * Lift effect+ Lift(..) , sendM+ -- * Lift carrier , runM , LiftC(..)+ -- * Re-exports+, Carrier+, Member+, run ) where import Control.Applicative (Alternative(..)) import Control.Effect.Carrier-import Control.Effect.Sum import Control.Monad (MonadPlus(..)) import Control.Monad.Fail+import Control.Monad.Fix import Control.Monad.IO.Class import Control.Monad.IO.Unlift import Control.Monad.Trans.Class+import GHC.Generics -newtype Lift sig (m :: * -> *) k = Lift { unLift :: sig k }- deriving stock Functor+newtype Lift sig m k = Lift { unLift :: sig (m k) }+ deriving stock (Functor, Generic1) deriving anyclass (HFunctor, Effect) -- | Extract a 'Lift'ed 'Monad'ic action from an effectful computation.@@ -30,7 +37,7 @@ sendM = send . Lift . fmap pure newtype LiftC m a = LiftC { runLiftC :: m a }- deriving newtype (Alternative, Applicative, Functor, Monad, MonadFail, MonadIO, MonadPlus)+ deriving newtype (Alternative, Applicative, Functor, Monad, MonadFail, MonadFix, MonadIO, MonadPlus) instance MonadTrans LiftC where lift = LiftC
src/Control/Effect/NonDet.hs view
@@ -1,32 +1,40 @@-{-# LANGUAGE DeriveAnyClass, DeriveFunctor, FlexibleInstances, GeneralizedNewtypeDeriving, KindSignatures, MultiParamTypeClasses, RankNTypes, TypeOperators, UndecidableInstances #-}+{-# LANGUAGE DeriveAnyClass, DeriveFunctor, DeriveGeneric, DerivingStrategies, FlexibleInstances, GeneralizedNewtypeDeriving, MultiParamTypeClasses, RankNTypes, TypeOperators, UndecidableInstances #-} module Control.Effect.NonDet-( NonDet(..)-, Alternative(..)+( -- * NonDet effect+ NonDet(..)+ -- * NonDet carrier , runNonDet , NonDetC(..)+ -- * Re-exports+, Alternative(..)+, Carrier+, Member+, run ) where import Control.Applicative (Alternative(..)) import Control.Effect.Carrier-import Control.Effect.Sum import Control.Monad (MonadPlus(..)) import Control.Monad.Fail+import Control.Monad.Fix import Control.Monad.IO.Class import Control.Monad.Trans.Class+import GHC.Generics (Generic1) import Prelude hiding (fail) -data NonDet (m :: * -> *) k+data NonDet m k = Empty- | Choose (Bool -> k)- deriving (Functor, HFunctor, Effect)+ | Choose (Bool -> m k)+ deriving stock (Functor, Generic1)+ deriving anyclass (HFunctor, Effect) -- | Run a 'NonDet' effect, collecting all branches’ results into an 'Alternative' functor. -- -- Using '[]' as the 'Alternative' functor will produce all results, while 'Maybe' will return only the first. However, unlike 'runNonDetOnce', this will still enumerate the entire search space before returning, meaning that it will diverge for infinite search spaces, even when using 'Maybe'. ----- prop> run (runNonDet (pure a)) == [a]--- prop> run (runNonDet (pure a)) == Just a+-- prop> run (runNonDet (pure a)) === [a]+-- prop> run (runNonDet (pure a)) === Just a runNonDet :: (Alternative f, Applicative m) => NonDetC m a -> m (f a) runNonDet (NonDetC m) = m (fmap . (<|>) . pure) (pure empty) @@ -35,7 +43,7 @@ { -- | A higher-order function receiving two parameters: a function to combine each solution with the rest of the solutions, and an action to run when no results are produced. runNonDetC :: forall b . (a -> m b -> m b) -> m b -> m b }- deriving (Functor)+ deriving stock (Functor) instance Applicative (NonDetC m) where pure a = NonDetC (\ cons -> cons a)@@ -58,6 +66,10 @@ instance MonadFail m => MonadFail (NonDetC m) where fail s = NonDetC (\ _ _ -> fail s) {-# INLINE fail #-}++instance MonadFix m => MonadFix (NonDetC m) where+ mfix f = NonDetC (\ cons nil -> mfix (\ a -> runNonDetC (f (head a)) (fmap . (:)) (pure [])) >>= foldr cons nil)+ {-# INLINE mfix #-} instance MonadIO m => MonadIO (NonDetC m) where liftIO io = NonDetC (\ cons nil -> liftIO io >>= flip cons nil)
src/Control/Effect/Pure.hs view
@@ -1,24 +1,20 @@-{-# LANGUAGE DeriveFunctor, EmptyCase, KindSignatures, MultiParamTypeClasses #-}+{-# LANGUAGE DeriveFunctor, DeriveGeneric, KindSignatures #-} module Control.Effect.Pure-( Pure+( -- * Pure effect+ Pure+ -- * Pure carrier , run , PureC(..) ) where import Control.Applicative-import Control.Effect.Carrier+import Control.Monad.Fix import Data.Coerce+import Data.Function (fix)+import GHC.Generics (Generic1) data Pure (m :: * -> *) k- deriving (Functor)--instance HFunctor Pure where- hmap _ v = case v of {}- {-# INLINE hmap #-}--instance Effect Pure where- handle _ _ v = case v of {}- {-# INLINE handle #-}+ deriving (Functor, Generic1) -- | Run an action exhausted of effects to produce its final result value.@@ -58,6 +54,6 @@ PureC a >>= f = f a {-# INLINE (>>=) #-} -instance Carrier Pure PureC where- eff v = case v of {}- {-# INLINE eff #-}+instance MonadFix PureC where+ mfix f = PureC (fix (runPureC . f))+ {-# INLINE mfix #-}
src/Control/Effect/Random.hs view
@@ -1,60 +1,66 @@ {-# LANGUAGE DeriveFunctor, ExistentialQuantification, FlexibleInstances, GeneralizedNewtypeDeriving, MultiParamTypeClasses, ScopedTypeVariables, StandaloneDeriving, TypeOperators, UndecidableInstances #-} module Control.Effect.Random-( Random(..)+( -- * Random effect+ Random(..)+ -- * Random carrier , runRandom , evalRandom , execRandom , evalRandomIO , RandomC(..)+ -- * Re-exports+, Carrier+, Member , MonadRandom(..) , MonadInterleave(..)+, run ) where import Control.Applicative (Alternative(..)) import Control.Effect.Carrier import Control.Effect.State-import Control.Effect.Sum import Control.Monad (MonadPlus(..)) import Control.Monad.Fail+import Control.Monad.Fix import Control.Monad.Random.Class (MonadInterleave(..), MonadRandom(..)) import Control.Monad.IO.Class (MonadIO(..)) import Control.Monad.Trans.Class import qualified System.Random as R (Random(..), RandomGen(..), StdGen, newStdGen) data Random m k- = forall a . R.Random a => Random (a -> k)- | forall a . R.Random a => RandomR (a, a) (a -> k)- | forall a . Interleave (m a) (a -> k)+ = forall a . R.Random a => Random (a -> m k)+ | forall a . R.Random a => RandomR (a, a) (a -> m k)+ | forall a . Interleave (m a) (a -> m k) -deriving instance Functor (Random m)+deriving instance Functor m => Functor (Random m) instance HFunctor Random where- hmap _ (Random k) = Random k- hmap _ (RandomR r k) = RandomR r k- hmap f (Interleave m k) = Interleave (f m) k+ hmap f (Random k) = Random (f . k)+ hmap f (RandomR r k) = RandomR r (f . k)+ hmap f (Interleave m k) = Interleave (f m) (f . k) {-# INLINE hmap #-} instance Effect Random where- handle state handler (Random k) = Random (handler . (<$ state) . k)- handle state handler (RandomR r k) = RandomR r (handler . (<$ state) . k)+ handle state handler (Random k) = Random (handler . (<$ state) . k)+ handle state handler (RandomR r k) = RandomR r (handler . (<$ state) . k) handle state handler (Interleave m k) = Interleave (handler (m <$ state)) (handler . fmap k) -- | Run a random computation starting from a given generator. ----- prop> run (runRandom (PureGen a) (pure b)) == (PureGen a, b)+-- prop> run (runRandom (PureGen a) (pure b)) === (PureGen a, b) runRandom :: g -> RandomC g m a -> m (g, a) runRandom g = runState g . runRandomC -- | Run a random computation starting from a given generator and discarding the final generator. ----- prop> run (evalRandom (PureGen a) (pure b)) == b+-- prop> run (evalRandom (PureGen a) (pure b)) === b evalRandom :: Functor m => g -> RandomC g m a -> m a evalRandom g = fmap snd . runRandom g -- | Run a random computation starting from a given generator and discarding the final result. ----- prop> run (execRandom (PureGen a) (pure b)) == PureGen a+-- prop> run (execRandom (PureGen a) (pure b)) === PureGen a execRandom :: Functor m => g -> RandomC g m a -> m g execRandom g = fmap fst . runRandom g @@ -63,7 +69,7 @@ evalRandomIO m = liftIO R.newStdGen >>= flip evalRandom m newtype RandomC g m a = RandomC { runRandomC :: StateC g m a }- deriving (Alternative, Applicative, Functor, Monad, MonadFail, MonadIO, MonadPlus, MonadTrans)+ deriving (Alternative, Applicative, Functor, Monad, MonadFail, MonadFix, MonadIO, MonadPlus, MonadTrans) instance (Carrier sig m, Effect sig, R.RandomGen g) => MonadRandom (RandomC g m) where getRandom = RandomC $ do
src/Control/Effect/Reader.hs view
@@ -1,32 +1,38 @@ {-# LANGUAGE DeriveFunctor, ExistentialQuantification, FlexibleContexts, FlexibleInstances, MultiParamTypeClasses, StandaloneDeriving, TypeOperators, UndecidableInstances #-} module Control.Effect.Reader-( Reader(..)+( -- * Reader effect+ Reader(..) , ask , asks , local+ -- * Reader carrier , runReader , ReaderC(..)+ -- * Re-exports+, Carrier+, Member+, run ) where import Control.Applicative (Alternative(..), liftA2) import Control.Effect.Carrier-import Control.Effect.Sum import Control.Monad (MonadPlus(..)) import Control.Monad.Fail+import Control.Monad.Fix import Control.Monad.IO.Class import Control.Monad.IO.Unlift import Control.Monad.Trans.Class import Prelude hiding (fail) data Reader r m k- = Ask (r -> k)- | forall b . Local (r -> r) (m b) (b -> k)+ = Ask (r -> m k)+ | forall b . Local (r -> r) (m b) (b -> m k) -deriving instance Functor (Reader r m)+deriving instance Functor m => Functor (Reader r m) instance HFunctor (Reader r) where- hmap _ (Ask k) = Ask k- hmap f (Local g m k) = Local g (f m) k+ hmap f (Ask k) = Ask (f . k)+ hmap f (Local g m k) = Local g (f m) (f . k) instance Effect (Reader r) where handle state handler (Ask k) = Ask (handler . (<$ state) . k)@@ -34,27 +40,27 @@ -- | Retrieve the environment value. ----- prop> run (runReader a ask) == a+-- prop> run (runReader a ask) === a ask :: (Member (Reader r) sig, Carrier sig m) => m r ask = send (Ask pure) -- | Project a function out of the current environment value. ----- prop> snd (run (runReader a (asks (applyFun f)))) == applyFun f a+-- prop> snd (run (runReader a (asks (applyFun f)))) === applyFun f a asks :: (Member (Reader r) sig, Carrier sig m) => (r -> a) -> m a asks f = send (Ask (pure . f)) -- | Run a computation with an environment value locally modified by the passed function. ----- prop> run (runReader a (local (applyFun f) ask)) == applyFun f a--- prop> run (runReader a ((,,) <$> ask <*> local (applyFun f) ask <*> ask)) == (a, applyFun f a, a)+-- prop> run (runReader a (local (applyFun f) ask)) === applyFun f a+-- prop> run (runReader a ((,,) <$> ask <*> local (applyFun f) ask <*> ask)) === (a, applyFun f a, a) local :: (Member (Reader r) sig, Carrier sig m) => (r -> r) -> m a -> m a local f m = send (Local f m pure) -- | Run a 'Reader' effect with the passed environment value. ----- prop> run (runReader a (pure b)) == b+-- prop> run (runReader a (pure b)) === b runReader :: r -> ReaderC r m a -> m a runReader r c = runReaderC c r {-# INLINE runReader #-}@@ -86,6 +92,10 @@ fail = ReaderC . const . fail {-# INLINE fail #-} +instance MonadFix m => MonadFix (ReaderC s m) where+ mfix f = ReaderC (\ r -> mfix (runReader r . f))+ {-# INLINE mfix #-}+ instance MonadIO m => MonadIO (ReaderC r m) where liftIO = ReaderC . const . liftIO {-# INLINE liftIO #-}@@ -105,7 +115,7 @@ instance Carrier sig m => Carrier (Reader r :+: sig) (ReaderC r m) where eff (L (Ask k)) = ReaderC (\ r -> runReader r (k r)) eff (L (Local f m k)) = ReaderC (\ r -> runReader (f r) m) >>= k- eff (R other) = ReaderC (\ r -> eff (handlePure (runReader r) other))+ eff (R other) = ReaderC (\ r -> eff (hmap (runReader r) other)) {-# INLINE eff #-}
src/Control/Effect/Resource.hs view
@@ -1,35 +1,36 @@ {-# LANGUAGE DeriveFunctor, ExistentialQuantification, FlexibleContexts, FlexibleInstances, GeneralizedNewtypeDeriving, MultiParamTypeClasses, RankNTypes, ScopedTypeVariables, StandaloneDeriving, TypeApplications, TypeOperators, UndecidableInstances #-} module Control.Effect.Resource-( Resource(..)+( -- * Resource effect+ Resource(..) , bracket , bracketOnError , finally , onException+ -- * Resource carrier , runResource-, withResource , ResourceC(..) ) where import Control.Applicative (Alternative(..)) import Control.Effect.Carrier import Control.Effect.Reader-import Control.Effect.Sum import qualified Control.Exception as Exc import Control.Monad (MonadPlus(..)) import Control.Monad.Fail+import Control.Monad.Fix import Control.Monad.IO.Class import Control.Monad.IO.Unlift import Control.Monad.Trans.Class data Resource m k- = forall resource any output . Resource (m resource) (resource -> m any) (resource -> m output) (output -> k)- | forall resource any output . OnError (m resource) (resource -> m any) (resource -> m output) (output -> k)+ = forall resource any output . Resource (m resource) (resource -> m any) (resource -> m output) (output -> m k)+ | forall resource any output . OnError (m resource) (resource -> m any) (resource -> m output) (output -> m k) -deriving instance Functor (Resource m)+deriving instance Functor m => Functor (Resource m) instance HFunctor Resource where- hmap f (Resource acquire release use k) = Resource (f acquire) (f . release) (f . use) k- hmap f (OnError acquire release use k) = OnError (f acquire) (f . release) (f . use) k+ hmap f (Resource acquire release use k) = Resource (f acquire) (f . release) (f . use) (f . k)+ hmap f (OnError acquire release use k) = OnError (f acquire) (f . release) (f . use) (f . k) instance Effect Resource where handle state handler (Resource acquire release use k) = Resource (handler (acquire <$ state)) (handler . fmap release) (handler . fmap use) (handler . fmap k)@@ -75,24 +76,34 @@ -> m a onException act end = bracketOnError (pure ()) (const end) (const act) -runResource :: (forall x . m x -> IO x) -- ^ "unlifting" function to run the carrier in 'IO'+-- Not exposed due to its potential to silently drop effects (#180).+unliftResource :: (forall x . m x -> IO x) -- ^ "unlifting" function to run the carrier in 'IO' -> ResourceC m a -> m a-runResource handler = runReader (Handler handler) . runResourceC+unliftResource handler = runReader (Handler handler) . runResourceC --- | A helper for 'runResource' that uses 'withRunInIO' to automatically--- select a correct unlifting function.-withResource :: MonadUnliftIO m- => ResourceC m a- -> m a-withResource r = withRunInIO (\f -> runHandler (Handler f) r)+-- | Executes a 'Resource' effect. Because this runs using 'MonadUnliftIO',+-- invocations of 'runResource' must happen at the "bottom" of a stack of+-- effect invocations, i.e. before the use of any monads that lack such+-- instances, such as 'StateC':+--+-- @+-- runM+-- . runResource+-- . runState @Int 1+-- $ myComputation+-- @+runResource :: MonadUnliftIO m+ => ResourceC m a+ -> m a+runResource r = withRunInIO (\f -> runHandler (Handler f) r) newtype ResourceC m a = ResourceC { runResourceC :: ReaderC (Handler m) m a }- deriving (Alternative, Applicative, Functor, Monad, MonadFail, MonadIO, MonadPlus)+ deriving (Alternative, Applicative, Functor, Monad, MonadFail, MonadFix, MonadIO, MonadPlus) instance MonadUnliftIO m => MonadUnliftIO (ResourceC m) where askUnliftIO = ResourceC . ReaderC $ \(Handler h) ->- withUnliftIO $ \u -> pure (UnliftIO $ \r -> unliftIO u (runResource h r))+ withUnliftIO $ \u -> pure (UnliftIO $ \r -> unliftIO u (unliftResource h r)) instance MonadTrans ResourceC where lift = ResourceC . lift
src/Control/Effect/Resumable.hs view
@@ -1,12 +1,18 @@-{-# LANGUAGE DeriveAnyClass, DeriveFunctor, DerivingStrategies, ExistentialQuantification, FlexibleContexts, FlexibleInstances, GeneralizedNewtypeDeriving, KindSignatures, MultiParamTypeClasses, RankNTypes, StandaloneDeriving, TypeOperators, UndecidableInstances #-}+{-# LANGUAGE DeriveFunctor, DerivingStrategies, ExistentialQuantification, FlexibleContexts, FlexibleInstances, GeneralizedNewtypeDeriving, MultiParamTypeClasses, RankNTypes, StandaloneDeriving, TypeOperators, UndecidableInstances #-} module Control.Effect.Resumable-( Resumable(..)+( -- * Resumable effect+ Resumable(..) , throwResumable , SomeError(..)+ -- * Resumable carriers , runResumable , ResumableC(..) , runResumableWith , ResumableWithC(..)+ -- * Re-exports+, Carrier+, Member+, run ) where import Control.Applicative (Alternative(..))@@ -14,38 +20,42 @@ import Control.Effect.Carrier import Control.Effect.Error import Control.Effect.Reader-import Control.Effect.Sum import Control.Monad (MonadPlus(..)) import Control.Monad.Fail+import Control.Monad.Fix import Control.Monad.IO.Class import Control.Monad.Trans.Class import Data.Functor.Classes -- | Errors which can be resumed with values of some existentially-quantified type.-data Resumable err (m :: * -> *) k- = forall a . Resumable (err a) (a -> k)+data Resumable err m k+ = forall a . Resumable (err a) (a -> m k) -deriving instance Functor (Resumable err m)-deriving instance HFunctor (Resumable err)-deriving instance Effect (Resumable err)+deriving instance Functor m => Functor (Resumable err m) +instance HFunctor (Resumable err) where+ hmap f (Resumable err k) = Resumable err (f . k)++instance Effect (Resumable err) where+ handle state handler (Resumable err k) = Resumable err (handler . (<$ state) . k)+ -- | Throw an error which can be resumed with a value of its result type. ----- prop> run (runResumable (throwResumable (Identity a))) == Left (SomeError (Identity a))+-- prop> run (runResumable (throwResumable (Identity a))) === Left (SomeError (Identity a)) throwResumable :: (Member (Resumable err) sig, Carrier sig m) => err a -> m a throwResumable err = send (Resumable err pure) -- | An error at some existentially-quantified type index.-data SomeError (err :: * -> *)+data SomeError err = forall a . SomeError (err a) -- | Equality for 'SomeError' is determined by an 'Eq1' instance for the error type. -- -- Note that since we can’t tell whether the type indices are equal, let alone what 'Eq' instance to use for them, the comparator passed to 'liftEq' always returns 'True'. Thus, 'SomeError' is best used with type-indexed GADTs for the error type. ----- prop> SomeError (Identity a) == SomeError (Identity b)--- prop> (SomeError (Const a) == SomeError (Const b)) == (a == b)+-- prop> SomeError (Identity a) === SomeError (Identity b)+-- prop> (SomeError (Const a) === SomeError (Const b)) == (a == b) instance Eq1 err => Eq (SomeError err) where SomeError exc1 == SomeError exc2 = liftEq (const (const True)) exc1 exc2 @@ -53,8 +63,8 @@ -- -- Note that since we can’t tell whether the type indices are equal, let alone what 'Ord' instance to use for them, the comparator passed to 'liftCompare' always returns 'EQ'. Thus, 'SomeError' is best used with type-indexed GADTs for the error type. ----- prop> (SomeError (Identity a) `compare` SomeError (Identity b)) == EQ--- prop> (SomeError (Const a) `compare` SomeError (Const b)) == (a `compare` b)+-- prop> (SomeError (Identity a) `compare` SomeError (Identity b)) === EQ+-- prop> (SomeError (Const a) `compare` SomeError (Const b)) === (a `compare` b) instance Ord1 err => Ord (SomeError err) where SomeError exc1 `compare` SomeError exc2 = liftCompare (const (const EQ)) exc1 exc2 @@ -62,8 +72,8 @@ -- -- Note that since we can’t tell what 'Show' instance to use for the type index, the functions passed to 'liftShowsPrec' always return the empty 'ShowS'. Thus, 'SomeError' is best used with type-indexed GADTs for the error type. ----- prop> show (SomeError (Identity a)) == "SomeError (Identity )"--- prop> show (SomeError (Const a)) == ("SomeError (Const " ++ showsPrec 11 a ")")+-- prop> show (SomeError (Identity a)) === "SomeError (Identity )"+-- prop> show (SomeError (Const a)) === ("SomeError (Const " ++ showsPrec 11 a ")") instance Show1 err => Show (SomeError err) where showsPrec d (SomeError err) = showsUnaryWith (liftShowsPrec (const (const id)) (const id)) "SomeError" d err @@ -77,12 +87,12 @@ -- | Run a 'Resumable' effect, returning uncaught errors in 'Left' and successful computations’ values in 'Right'. ----- prop> run (runResumable (pure a)) == Right @(SomeError Identity) @Int a+-- prop> run (runResumable (pure a)) === Right @(SomeError Identity) @Int a runResumable :: ResumableC err m a -> m (Either (SomeError err) a) runResumable = runError . runResumableC newtype ResumableC err m a = ResumableC { runResumableC :: ErrorC (SomeError err) m a }- deriving newtype (Alternative, Applicative, Functor, Monad, MonadFail, MonadIO, MonadPlus, MonadTrans)+ deriving newtype (Alternative, Applicative, Functor, Monad, MonadFail, MonadFix, MonadIO, MonadPlus, MonadTrans) instance (Carrier sig m, Effect sig) => Carrier (Resumable err :+: sig) (ResumableC err m) where eff (L (Resumable err _)) = ResumableC (throwError (SomeError err))@@ -96,15 +106,15 @@ -- -- >>> data Err a where Err :: Int -> Err Int ----- prop> run (runResumableWith (\ (Err b) -> pure (1 + b)) (pure a)) == a--- prop> run (runResumableWith (\ (Err b) -> pure (1 + b)) (throwResumable (Err a))) == 1 + a+-- prop> run (runResumableWith (\ (Err b) -> pure (1 + b)) (pure a)) === a+-- prop> run (runResumableWith (\ (Err b) -> pure (1 + b)) (throwResumable (Err a))) === 1 + a runResumableWith :: (forall x . err x -> m x) -> ResumableWithC err m a -> m a runResumableWith with = runReader (Handler with) . runResumableWithC newtype ResumableWithC err m a = ResumableWithC { runResumableWithC :: ReaderC (Handler err m) m a }- deriving newtype (Alternative, Applicative, Functor, Monad, MonadFail, MonadIO, MonadPlus)+ deriving newtype (Alternative, Applicative, Functor, Monad, MonadFail, MonadFix, MonadIO, MonadPlus) instance MonadTrans (ResumableWithC err) where lift = ResumableWithC . lift
src/Control/Effect/State/Internal.hs view
@@ -1,41 +1,45 @@-{-# LANGUAGE DeriveAnyClass, DeriveFunctor, ExplicitForAll, FlexibleContexts, FlexibleInstances, KindSignatures, MultiParamTypeClasses, TypeOperators, UndecidableInstances #-}+{-# LANGUAGE DeriveAnyClass, DeriveFunctor, DeriveGeneric, DerivingStrategies, ExplicitForAll, FlexibleContexts, FlexibleInstances, MultiParamTypeClasses, TypeOperators, UndecidableInstances #-} module Control.Effect.State.Internal-( State(..)+( -- * State effect+ State(..) , get , gets , put , modify , modifyLazy+ -- * Re-exports+, Member ) where import Control.Effect.Carrier-import Control.Effect.Sum+import GHC.Generics (Generic1) import Prelude hiding (fail) -data State s (m :: * -> *) k- = Get (s -> k)- | Put s k- deriving (Functor, HFunctor, Effect)+data State s m k+ = Get (s -> m k)+ | Put s (m k)+ deriving stock (Functor, Generic1)+ deriving anyclass (HFunctor, Effect) -- | Get the current state value. ----- prop> snd (run (runState a get)) == a+-- prop> snd (run (runState a get)) === a get :: (Member (State s) sig, Carrier sig m) => m s get = send (Get pure) {-# INLINEABLE get #-} -- | Project a function out of the current state value. ----- prop> snd (run (runState a (gets (applyFun f)))) == applyFun f a+-- prop> snd (run (runState a (gets (applyFun f)))) === applyFun f a gets :: (Member (State s) sig, Carrier sig m) => (s -> a) -> m a gets f = send (Get (pure . f)) {-# INLINEABLE gets #-} -- | Replace the state value with a new value. ----- prop> fst (run (runState a (put b))) == b--- prop> snd (run (runState a (get <* put b))) == a--- prop> snd (run (runState a (put b *> get))) == b+-- prop> fst (run (runState a (put b))) === b+-- prop> snd (run (runState a (get <* put b))) === a+-- prop> snd (run (runState a (put b *> get))) === b put :: (Member (State s) sig, Carrier sig m) => s -> m () put s = send (Put s (pure ())) {-# INLINEABLE put #-}@@ -43,7 +47,7 @@ -- | Replace the state value with the result of applying a function to the current state value. -- This is strict in the new state. ----- prop> fst (run (runState a (modify (+1)))) == (1 + a :: Integer)+-- prop> fst (run (runState a (modify (+1)))) === (1 + a :: Integer) modify :: (Member (State s) sig, Carrier sig m) => (s -> s) -> m () modify f = do a <- get
src/Control/Effect/State/Lazy.hs view
@@ -1,23 +1,23 @@-{-# LANGUAGE DeriveFunctor, ExplicitForAll, FlexibleContexts, FlexibleInstances, KindSignatures, MultiParamTypeClasses, TypeOperators, UndecidableInstances #-}+{-# LANGUAGE DeriveFunctor, ExplicitForAll, FlexibleContexts, FlexibleInstances, MultiParamTypeClasses, TypeOperators, UndecidableInstances #-} module Control.Effect.State.Lazy-( State (..)-, get-, gets-, put-, modify-, modifyLazy-, StateC(..)+( -- * State effect+ module State+ -- * Lazy state carrier , runState , evalState , execState+, StateC(..)+ -- * Re-exports+, Carrier+, run ) where import Control.Applicative (Alternative(..)) import Control.Effect.Carrier-import Control.Effect.Sum-import Control.Effect.State.Internal+import Control.Effect.State.Internal as State import Control.Monad (MonadPlus(..)) import Control.Monad.Fail+import Control.Monad.Fix import Control.Monad.IO.Class import Control.Monad.Trans.Class import Prelude hiding (fail)@@ -55,6 +55,10 @@ fail s = StateC (const (fail s)) {-# INLINE fail #-} +instance MonadFix m => MonadFix (StateC s m) where+ mfix f = StateC (\ s -> mfix (runState s . f . snd))+ {-# INLINE mfix #-}+ instance MonadIO m => MonadIO (StateC s m) where liftIO io = StateC (\ s -> (,) s <$> liftIO io) {-# INLINE liftIO #-}@@ -75,22 +79,22 @@ -- More programs terminate with lazy state than strict state, but injudicious -- use of lazy state may lead to thunk buildup. ----- prop> run (runState a (pure b)) == (a, b)--- prop> take 5 . snd . run $ runState () (traverse pure [1..]) == [1,2,3,4,5]+-- prop> run (runState a (pure b)) === (a, b)+-- prop> take 5 . snd . run $ runState () (traverse pure [1..]) === [1,2,3,4,5] runState :: s -> StateC s m a -> m (s, a) runState s c = runStateC c s {-# INLINE[3] runState #-} -- | Run a lazy 'State' effect, yielding the result value and discarding the final state. ----- prop> run (evalState a (pure b)) == b+-- prop> run (evalState a (pure b)) === b evalState :: forall s m a . Functor m => s -> StateC s m a -> m a evalState s = fmap snd . runState s {-# INLINE[3] evalState #-} -- | Run a lazy 'State' effect, yielding the final state and discarding the return value. ----- prop> run (execState a (pure b)) == a+-- prop> run (execState a (pure b)) === a execState :: forall s m a . Functor m => s -> StateC s m a -> m s execState s = fmap fst . runState s {-# INLINE[3] execState #-}
src/Control/Effect/State/Strict.hs view
@@ -1,44 +1,44 @@-{-# LANGUAGE DeriveFunctor, ExplicitForAll, FlexibleContexts, FlexibleInstances, KindSignatures, MultiParamTypeClasses, TypeOperators, UndecidableInstances #-}+{-# LANGUAGE DeriveFunctor, ExplicitForAll, FlexibleContexts, FlexibleInstances, MultiParamTypeClasses, TypeOperators, UndecidableInstances #-} module Control.Effect.State.Strict-( State (..)-, get-, gets-, put-, modify-, modifyLazy-, StateC(..)+( -- * State effect+ module State+ -- * Strict state carrier , runState , evalState , execState+, StateC(..)+ -- * Re-exports+, Carrier+, run ) where import Control.Applicative (Alternative(..)) import Control.Effect.Carrier-import Control.Effect.State.Internal-import Control.Effect.Sum+import Control.Effect.State.Internal as State import Control.Monad (MonadPlus(..)) import Control.Monad.Fail+import Control.Monad.Fix import Control.Monad.IO.Class import Control.Monad.Trans.Class import Prelude hiding (fail) -- | Run a 'State' effect starting from the passed value. ----- prop> run (runState a (pure b)) == (a, b)+-- prop> run (runState a (pure b)) === (a, b) runState :: s -> StateC s m a -> m (s, a) runState s x = runStateC x s {-# INLINE[3] runState #-} -- | Run a 'State' effect, yielding the result value and discarding the final state. ----- prop> run (evalState a (pure b)) == b+-- prop> run (evalState a (pure b)) === b evalState :: forall s m a . Functor m => s -> StateC s m a -> m a evalState s = fmap snd . runState s {-# INLINE[3] evalState #-} -- | Run a 'State' effect, yielding the final state and discarding the return value. ----- prop> run (execState a (pure b)) == a+-- prop> run (execState a (pure b)) === a execState :: forall s m a . Functor m => s -> StateC s m a -> m s execState s = fmap fst . runState s {-# INLINE[3] execState #-}@@ -75,6 +75,10 @@ instance MonadFail m => MonadFail (StateC s m) where fail s = StateC (const (fail s)) {-# INLINE fail #-}++instance MonadFix m => MonadFix (StateC s m) where+ mfix f = StateC (\ s -> mfix (runState s . f . snd))+ {-# INLINE mfix #-} instance MonadIO m => MonadIO (StateC s m) where liftIO io = StateC (\ s -> (,) s <$> liftIO io)
src/Control/Effect/Sum.hs view
@@ -1,30 +1,18 @@-{-# LANGUAGE DeriveFunctor, FlexibleInstances, KindSignatures, MultiParamTypeClasses, TypeOperators #-}+{-# LANGUAGE DeriveGeneric, DeriveTraversable, FlexibleInstances, KindSignatures, MultiParamTypeClasses, TypeOperators #-} module Control.Effect.Sum ( (:+:)(..) , Member(..)-, send ) where -import Control.Effect.Carrier+import GHC.Generics (Generic1) data (f :+: g) (m :: * -> *) k = L (f m k) | R (g m k)- deriving (Eq, Functor, Ord, Show)+ deriving (Eq, Foldable, Functor, Generic1, Ord, Show, Traversable) infixr 4 :+: -instance (HFunctor l, HFunctor r) => HFunctor (l :+: r) where- hmap f (L l) = L (hmap f l)- hmap f (R r) = R (hmap f r)-- fmap' f (L l) = L (fmap' f l)- fmap' f (R r) = R (fmap' f r)--instance (Effect l, Effect r) => Effect (l :+: r) where- handle state handler (L l) = L (handle state handler l)- handle state handler (R r) = R (handle state handler r)- class Member (sub :: (* -> *) -> (* -> *)) sup where inj :: sub m a -> sup m a prj :: sup m a -> Maybe (sub m a)@@ -42,9 +30,3 @@ inj = R . inj prj (R g) = prj g prj _ = Nothing----- | Construct a request for an effect to be interpreted by some handler later on.-send :: (Member effect sig, Carrier sig m) => effect m (m a) -> m a-send = eff . inj-{-# INLINE send #-}
src/Control/Effect/Trace.hs view
@@ -1,31 +1,39 @@-{-# LANGUAGE DeriveAnyClass, DeriveFunctor, DerivingStrategies, FlexibleContexts, FlexibleInstances, GeneralizedNewtypeDeriving, KindSignatures, MultiParamTypeClasses, TypeOperators, UndecidableInstances #-}+{-# LANGUAGE DeriveAnyClass, DeriveFunctor, DeriveGeneric, DerivingStrategies, FlexibleContexts, FlexibleInstances, GeneralizedNewtypeDeriving, MultiParamTypeClasses, TypeOperators, UndecidableInstances #-} module Control.Effect.Trace-( Trace(..)+( -- * Trace effect+ Trace(..) , trace+ -- * Trace carriers , runTraceByPrinting , TraceByPrintingC(..) , runTraceByIgnoring , TraceByIgnoringC(..) , runTraceByReturning , TraceByReturningC(..)+ -- * Re-exports+, Carrier+, Member+, run ) where import Control.Applicative (Alternative(..)) import Control.Effect.Carrier import Control.Effect.State-import Control.Effect.Sum import Control.Monad (MonadPlus(..)) import Control.Monad.Fail+import Control.Monad.Fix import Control.Monad.IO.Class import Control.Monad.Trans.Class import Data.Bifunctor (first)+import GHC.Generics (Generic1) import System.IO -data Trace (m :: * -> *) k = Trace+data Trace m k = Trace { traceMessage :: String- , traceCont :: k- } deriving stock Functor- deriving anyclass (HFunctor, Effect)+ , traceCont :: m k+ }+ deriving stock (Functor, Generic1)+ deriving anyclass (HFunctor, Effect) -- | Append a message to the trace log. trace :: (Member Trace sig, Carrier sig m) => String -> m ()@@ -37,7 +45,7 @@ runTraceByPrinting = runTraceByPrintingC newtype TraceByPrintingC m a = TraceByPrintingC { runTraceByPrintingC :: m a }- deriving newtype (Alternative, Applicative, Functor, Monad, MonadFail, MonadIO, MonadPlus)+ deriving newtype (Alternative, Applicative, Functor, Monad, MonadFail, MonadFix, MonadIO, MonadPlus) instance MonadTrans TraceByPrintingC where lift = TraceByPrintingC@@ -51,12 +59,12 @@ -- | Run a 'Trace' effect, ignoring all traces. ----- prop> run (runTraceByIgnoring (trace a *> pure b)) == b+-- prop> run (runTraceByIgnoring (trace a *> pure b)) === b runTraceByIgnoring :: TraceByIgnoringC m a -> m a runTraceByIgnoring = runTraceByIgnoringC newtype TraceByIgnoringC m a = TraceByIgnoringC { runTraceByIgnoringC :: m a }- deriving newtype (Alternative, Applicative, Functor, Monad, MonadFail, MonadIO, MonadPlus)+ deriving newtype (Alternative, Applicative, Functor, Monad, MonadFail, MonadFix, MonadIO, MonadPlus) instance MonadTrans TraceByIgnoringC where lift = TraceByIgnoringC@@ -70,12 +78,12 @@ -- | Run a 'Trace' effect, returning all traces as a list. ----- prop> run (runTraceByReturning (trace a *> trace b *> pure c)) == ([a, b], c)+-- prop> run (runTraceByReturning (trace a *> trace b *> pure c)) === ([a, b], c) runTraceByReturning :: Functor m => TraceByReturningC m a -> m ([String], a) runTraceByReturning = fmap (first reverse) . runState [] . runTraceByReturningC newtype TraceByReturningC m a = TraceByReturningC { runTraceByReturningC :: StateC [String] m a }- deriving newtype (Alternative, Applicative, Functor, Monad, MonadFail, MonadIO, MonadPlus, MonadTrans)+ deriving newtype (Alternative, Applicative, Functor, Monad, MonadFail, MonadFix, MonadIO, MonadPlus, MonadTrans) instance (Carrier sig m, Effect sig) => Carrier (Trace :+: sig) (TraceByReturningC m) where eff (L (Trace m k)) = TraceByReturningC (modify (m :)) *> k
src/Control/Effect/Writer.hs view
@@ -1,35 +1,41 @@ {-# LANGUAGE DeriveFunctor, ExistentialQuantification, FlexibleContexts, FlexibleInstances, GeneralizedNewtypeDeriving, MultiParamTypeClasses, ScopedTypeVariables, StandaloneDeriving, TypeOperators, UndecidableInstances #-} module Control.Effect.Writer-( Writer(..)+( -- * Writer effect+ Writer(..) , tell , listen , listens , censor+ -- * Writer carrier , runWriter , execWriter , WriterC(..)+ -- * Re-exports+, Carrier+, Member+, run ) where import Control.Applicative (Alternative(..)) import Control.Effect.Carrier import Control.Effect.State-import Control.Effect.Sum import Control.Monad (MonadPlus(..)) import Control.Monad.Fail+import Control.Monad.Fix import Control.Monad.IO.Class import Control.Monad.Trans.Class data Writer w m k- = Tell w k- | forall a . Listen (m a) (w -> a -> k)- | forall a . Censor (w -> w) (m a) (a -> k)+ = Tell w (m k)+ | forall a . Listen (m a) (w -> a -> m k)+ | forall a . Censor (w -> w) (m a) (a -> m k) -deriving instance Functor (Writer w m)+deriving instance Functor m => Functor (Writer w m) instance HFunctor (Writer w) where- hmap _ (Tell w k) = Tell w k- hmap f (Listen m k) = Listen (f m) k- hmap f (Censor g m k) = Censor g (f m) k+ hmap f (Tell w k) = Tell w (f k)+ hmap f (Listen m k) = Listen (f m) ((f .) . k)+ hmap f (Censor g m k) = Censor g (f m) (f . k) {-# INLINE hmap #-} instance Effect (Writer w) where@@ -40,29 +46,29 @@ -- | Write a value to the log. ----- prop> fst (run (runWriter (mapM_ (tell . Sum) (0 : ws)))) == foldMap Sum ws+-- prop> fst (run (runWriter (mapM_ (tell . Sum) (0 : ws)))) === foldMap Sum ws tell :: (Member (Writer w) sig, Carrier sig m) => w -> m () tell w = send (Tell w (pure ())) {-# INLINE tell #-} -- | Run a computation, returning the pair of its output and its result. ----- prop> run (runWriter (fst <$ tell (Sum a) <*> listen @(Sum Integer) (tell (Sum b)))) == (Sum a <> Sum b, Sum b)+-- prop> run (runWriter (fst <$ tell (Sum a) <*> listen @(Sum Integer) (tell (Sum b)))) === (Sum a <> Sum b, Sum b) listen :: (Member (Writer w) sig, Carrier sig m) => m a -> m (w, a) listen m = send (Listen m (curry pure)) {-# INLINE listen #-} -- | Run a computation, applying a function to its output and returning the pair of the modified output and its result. ----- prop> run (runWriter (fst <$ tell (Sum a) <*> listens @(Sum Integer) (applyFun f) (tell (Sum b)))) == (Sum a <> Sum b, applyFun f (Sum b))+-- prop> run (runWriter (fst <$ tell (Sum a) <*> listens @(Sum Integer) (applyFun f) (tell (Sum b)))) === (Sum a <> Sum b, applyFun f (Sum b)) listens :: (Member (Writer w) sig, Carrier sig m) => (w -> b) -> m a -> m (b, a) listens f m = send (Listen m (curry pure . f)) {-# INLINE listens #-} -- | Run a computation, modifying its output with the passed function. ----- prop> run (execWriter (censor (applyFun f) (tell (Sum a)))) == applyFun f (Sum a)--- prop> run (execWriter (tell (Sum a) *> censor (applyFun f) (tell (Sum b)) *> tell (Sum c))) == (Sum a <> applyFun f (Sum b) <> Sum c)+-- prop> run (execWriter (censor (applyFun f) (tell (Sum a)))) === applyFun f (Sum a)+-- prop> run (execWriter (tell (Sum a) *> censor (applyFun f) (tell (Sum b)) *> tell (Sum c))) === (Sum a <> applyFun f (Sum b) <> Sum c) censor :: (Member (Writer w) sig, Carrier sig m) => (w -> w) -> m a -> m a censor f m = send (Censor f m pure) {-# INLINE censor #-}@@ -70,14 +76,14 @@ -- | Run a 'Writer' effect with a 'Monoid'al log, producing the final log alongside the result value. ----- prop> run (runWriter (tell (Sum a) *> pure b)) == (Sum a, b)+-- prop> run (runWriter (tell (Sum a) *> pure b)) === (Sum a, b) runWriter :: Monoid w => WriterC w m a -> m (w, a) runWriter = runState mempty . runWriterC {-# INLINE runWriter #-} -- | Run a 'Writer' effect with a 'Monoid'al log, producing the final log and discarding the result value. ----- prop> run (execWriter (tell (Sum a) *> pure b)) == Sum a+-- prop> run (execWriter (tell (Sum a) *> pure b)) === Sum a execWriter :: (Monoid w, Functor m) => WriterC w m a -> m w execWriter = fmap fst . runWriter {-# INLINE execWriter #-}@@ -87,7 +93,7 @@ -- -- This is based on a post Gabriel Gonzalez made to the Haskell mailing list: https://mail.haskell.org/pipermail/libraries/2013-March/019528.html newtype WriterC w m a = WriterC { runWriterC :: StateC w m a }- deriving (Alternative, Applicative, Functor, Monad, MonadFail, MonadIO, MonadPlus, MonadTrans)+ deriving (Alternative, Applicative, Functor, Monad, MonadFail, MonadFix, MonadIO, MonadPlus, MonadTrans) instance (Monoid w, Carrier sig m, Effect sig) => Carrier (Writer w :+: sig) (WriterC w m) where eff (L (Tell w k)) = WriterC $ do
test/Control/Effect/NonDet/Spec.hs view
@@ -1,6 +1,7 @@-module Control.Effect.NonDet.Spec where+module Control.Effect.NonDet.Spec+( spec+) where -import Control.Effect import Control.Effect.Error import Control.Effect.NonDet import Control.Effect.State
test/Control/Effect/Spec.hs view
@@ -1,18 +1,17 @@ {-# LANGUAGE FlexibleContexts, FlexibleInstances, GeneralizedNewtypeDeriving, MultiParamTypeClasses, MultiWayIf, TemplateHaskell, TypeApplications, TypeOperators, UndecidableInstances #-} {-# OPTIONS_GHC -O2 -fplugin Test.Inspection.Plugin #-}-module Control.Effect.Spec where+module Control.Effect.Spec+( spec+) where -import Control.Effect import Control.Effect.Carrier import Control.Effect.Error import Control.Effect.Fail import Control.Effect.Reader import Control.Effect.State-import Control.Effect.Sum import Prelude hiding (fail) import Test.Hspec import Test.Inspection as Inspection-import Test.Inspection.Plugin spec :: Spec spec = do@@ -29,7 +28,7 @@ askEnv :: (Member (Reader env) sig, Carrier sig m) => HasEnv env m env askEnv = ask -runEnv :: Carrier sig m => env -> HasEnv env (ReaderC env m) a -> HasEnv env m a+runEnv :: env -> HasEnv env (ReaderC env m) a -> HasEnv env m a runEnv r = HasEnv . runReader r . runHasEnv @@ -111,13 +110,12 @@ countBoth :: Int -> (Int, (Float, ())) countBoth n = run . runState n . runState (fromIntegral n) $ go where go = do- int <- get @Int+ n <- get @Int if | n == 0 -> pure () | n `mod` 2 == 0 -> modify @Float (+ 1) *> modify @Int pred *> go- | otherwise -> modify @Int pred *> go+ | otherwise -> modify @Int pred *> go throwing :: Int -> Either Int String throwing n = run $ runError go where go = if n > 10 then throwError @Int 42 else pure "fine"-
test/Spec.hs view
@@ -1,4 +1,6 @@-module Main where+module Main+( main+) where import qualified Control.Effect.Spec import qualified Control.Effect.NonDet.Spec