Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions effectful-core/effectful-core.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ library
Effectful.Fail
Effectful.Internal.Effect
Effectful.Internal.Env
Effectful.Internal.MTL
Effectful.Internal.Monad
Effectful.Internal.Unlift
Effectful.Internal.Utils
Expand Down
1 change: 1 addition & 0 deletions effectful-core/src/Effectful.hs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ import Control.Monad.IO.Unlift

import Effectful.Internal.Effect
import Effectful.Internal.Env
import Effectful.Internal.MTL ()
import Effectful.Internal.Monad

-- $intro
Expand Down
27 changes: 3 additions & 24 deletions effectful-core/src/Effectful/Error/Dynamic.hs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
{-# OPTIONS_GHC -Wno-orphans #-}
-- | The dynamically dispatched variant of the 'Error' effect.
--
-- /Note:/ unless you plan to change interpretations at runtime or you need the
-- 'MTL.MonadError' instance for compatibility with existing code, it's
-- recommended to use the statically dispatched variant,
-- t'Control.Monad.Error.MonadError' instance for compatibility with existing
-- code, it's recommended to use the statically dispatched variant,
-- i.e. "Effectful.Error.Static".
module Effectful.Error.Dynamic
( -- * Effect
Expand All @@ -30,20 +29,12 @@ module Effectful.Error.Dynamic
, E.prettyCallStack
) where

import Control.Monad.Except qualified as MTL
import GHC.Stack (withFrozenCallStack)

import Effectful
import Effectful.Dispatch.Dynamic
import Effectful.Error.Static qualified as E

-- | Provide the ability to handle errors of type @e@.
data Error e :: Effect where
-- | @since 2.4.0.0
ThrowErrorWith :: (e -> String) -> e -> Error e m a
CatchError :: m a -> (E.CallStack -> e -> m a) -> Error e m a

type instance DispatchOf (Error e) = Dynamic
import Effectful.Internal.MTL (Error(..))

-- | Handle errors of type @e@ (via "Effectful.Error.Static").
runError
Expand Down Expand Up @@ -151,15 +142,3 @@ tryError
-- ^ The inner computation.
-> Eff es (Either (E.CallStack, e) a)
tryError m = (Right <$> m) `catchError` \es e -> pure $ Left (es, e)

----------------------------------------
-- Orphan instance

-- | Instance included for compatibility with existing code.
instance
( Show e
, Error e :> es
, MTL.MonadError e (Eff es)
) => MTL.MonadError e (Eff es) where
throwError = send . ThrowErrorWith show
catchError action = send . CatchError action . const
90 changes: 90 additions & 0 deletions effectful-core/src/Effectful/Internal/MTL.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
{-# OPTIONS_GHC -Wno-orphans #-}
-- | Definitions and instances for MTL compatibility.
--
-- This module is intended for internal use only, and may change without warning
-- in subsequent releases.
module Effectful.Internal.MTL where

import Control.Monad.Except qualified as MTL
import Control.Monad.Reader qualified as MTL
import Control.Monad.State qualified as MTL
import Control.Monad.Writer qualified as MTL
import GHC.Stack (CallStack)

import Effectful.Internal.Effect
import Effectful.Internal.Env
import Effectful.Internal.Monad

-- | Provide the ability to handle errors of type @e@.
data Error e :: Effect where
-- | @since 2.4.0.0
ThrowErrorWith :: (e -> String) -> e -> Error e m a
CatchError :: m a -> (CallStack -> e -> m a) -> Error e m a

type instance DispatchOf (Error e) = Dynamic

-- | Instance included for compatibility with existing code.
instance
( Show e
, Error e :> es
, MTL.MonadError e (Eff es)
) => MTL.MonadError e (Eff es) where
throwError = send . ThrowErrorWith show
catchError action = send . CatchError action . const

----------------------------------------

data Reader r :: Effect where
Ask :: Reader r m r
Local :: (r -> r) -> m a -> Reader r m a

type instance DispatchOf (Reader r) = Dynamic

-- | Instance included for compatibility with existing code.
instance
( Reader r :> es
, MTL.MonadReader r (Eff es)
) => MTL.MonadReader r (Eff es) where
ask = send Ask
local f = send . Local f
reader f = f <$> send Ask

----------------------------------------

-- | Provide access to a mutable value of type @s@.
data State s :: Effect where
Get :: State s m s
Put :: s -> State s m ()
State :: (s -> (a, s)) -> State s m a
StateM :: (s -> m (a, s)) -> State s m a

type instance DispatchOf (State s) = Dynamic

-- | Instance included for compatibility with existing code.
instance
( State s :> es
, MTL.MonadState s (Eff es)
) => MTL.MonadState s (Eff es) where
get = send Get
put = send . Put
state = send . State

----------------------------------------

-- | Provide access to a write only value of type @w@.
data Writer w :: Effect where
Tell :: w -> Writer w m ()
Listen :: m a -> Writer w m (a, w)

type instance DispatchOf (Writer w) = Dynamic

-- | Instance included for compatibility with existing code.
instance
( Monoid w
, Writer w :> es
, MTL.MonadWriter w (Eff es)
) => MTL.MonadWriter w (Eff es) where
writer (a, w) = a <$ send (Tell w)
tell = send . Tell
listen = send . Listen
pass = error "pass is not implemented due to ambiguous semantics in presence of runtime exceptions"
26 changes: 3 additions & 23 deletions effectful-core/src/Effectful/Reader/Dynamic.hs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
{-# OPTIONS_GHC -Wno-orphans #-}
-- | The dynamically dispatched variant of the 'Reader' effect.
--
-- /Note:/ unless you plan to change interpretations at runtime or you need the
-- 'MTL.MonadReader' instance for compatibility with existing code, it's
-- recommended to use the statically dispatched variant,
-- t'Control.Monad.Reader.MonadReader' instance for compatibility with existing
-- code, it's recommended to use the statically dispatched variant,
-- i.e. "Effectful.Reader.Static".
module Effectful.Reader.Dynamic
( -- * Effect
Expand All @@ -19,16 +18,9 @@ module Effectful.Reader.Dynamic
, local
) where

import Control.Monad.Reader qualified as MTL

import Effectful
import Effectful.Dispatch.Dynamic

data Reader r :: Effect where
Ask :: Reader r m r
Local :: (r -> r) -> m a -> Reader r m a

type instance DispatchOf (Reader r) = Dynamic
import Effectful.Internal.MTL (Reader(..))

-- | Run the 'Reader' effect with the given initial environment.
runReader
Expand Down Expand Up @@ -85,15 +77,3 @@ local
-> Eff es a
-> Eff es a
local f = send . Local f

----------------------------------------
-- Orphan instance

-- | Instance included for compatibility with existing code.
instance
( Reader r :> es
, MTL.MonadReader r (Eff es)
) => MTL.MonadReader r (Eff es) where
ask = send Ask
local f = send . Local f
reader f = f <$> send Ask
29 changes: 3 additions & 26 deletions effectful-core/src/Effectful/State/Dynamic.hs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
{-# OPTIONS_GHC -Wno-orphans #-}
-- | The dynamically dispatched variant of the 'State' effect.
--
-- /Note:/ unless you plan to change interpretations at runtime or you need the
-- 'MTL.MonadState' instance for compatibility with existing code, it's
-- recommended to use one of the statically dispatched variants,
-- t'Control.Monad.State.MonadState' instance for compatibility with existing
-- code, it's recommended to use one of the statically dispatched variants,
-- i.e. "Effectful.State.Static.Local" or "Effectful.State.Static.Shared".
module Effectful.State.Dynamic
( -- * Effect
Expand Down Expand Up @@ -31,22 +30,12 @@ module Effectful.State.Dynamic
, modifyM
) where

import Control.Monad.State qualified as MTL

import Effectful
import Effectful.Dispatch.Dynamic
import Effectful.Internal.MTL (State(..))
import Effectful.State.Static.Local qualified as L
import Effectful.State.Static.Shared qualified as S

-- | Provide access to a mutable value of type @s@.
data State s :: Effect where
Get :: State s m s
Put :: s -> State s m ()
State :: (s -> (a, s)) -> State s m a
StateM :: (s -> m (a, s)) -> State s m a

type instance DispatchOf (State s) = Dynamic

----------------------------------------
-- Local

Expand Down Expand Up @@ -153,15 +142,3 @@ modifyM
=> (s -> Eff es s)
-> Eff es ()
modifyM f = stateM (\s -> ((), ) <$> f s)

----------------------------------------
-- Orphan instance

-- | Instance included for compatibility with existing code.
instance
( State s :> es
, MTL.MonadState s (Eff es)
) => MTL.MonadState s (Eff es) where
get = send Get
put = send . Put
state = send . State
28 changes: 3 additions & 25 deletions effectful-core/src/Effectful/Writer/Dynamic.hs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
-- | The dynamically dispatched variant of the 'Writer' effect.
--
-- /Note:/ unless you plan to change interpretations at runtime or you need the
-- 'MTL.MonadWriter' instance for compatibility with existing code, it's
-- recommended to use one of the statically dispatched variants,
-- t'Control.Monad.Writer.MonadWriter' instance for compatibility with existing
-- code, it's recommended to use one of the statically dispatched variants,
-- i.e. "Effectful.Writer.Static.Local" or "Effectful.Writer.Static.Shared".
module Effectful.Writer.Dynamic
( -- * Effect
Expand All @@ -25,20 +25,12 @@ module Effectful.Writer.Dynamic
, listens
) where

import Control.Monad.Writer qualified as MTL

import Effectful
import Effectful.Dispatch.Dynamic
import Effectful.Internal.MTL (Writer(..))
import Effectful.Writer.Static.Local qualified as L
import Effectful.Writer.Static.Shared qualified as S

-- | Provide access to a write only value of type @w@.
data Writer w :: Effect where
Tell :: w -> Writer w m ()
Listen :: m a -> Writer w m (a, w)

type instance DispatchOf (Writer w) = Dynamic

----------------------------------------
-- Local

Expand Down Expand Up @@ -106,17 +98,3 @@ listens
listens f m = do
(a, w) <- listen m
pure (a, f w)

----------------------------------------
-- Orphan instance

-- | Instance included for compatibility with existing code.
instance
( Monoid w
, Writer w :> es
, MTL.MonadWriter w (Eff es)
) => MTL.MonadWriter w (Eff es) where
writer (a, w) = a <$ send (Tell w)
tell = send . Tell
listen = send . Listen
pass = error "pass is not implemented due to ambiguous semantics in presence of runtime exceptions"
Loading