Skip to content

Commit 68dbfeb

Browse files
committed
A more composable interface for monads
After trying my first attempt out, it required too much duplication of code and some unclear interaction with IO-specific code. This seems to work much better.
1 parent dae85e2 commit 68dbfeb

File tree

1 file changed

+13
-13
lines changed

1 file changed

+13
-13
lines changed

src/Benign.hs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,9 @@ module Benign
4646

4747
-- * Monads
4848
EvalM (..),
49+
withAlteringM,
4950
withSettingM,
51+
unsafeSpanBenignM,
5052
)
5153
where
5254

@@ -369,25 +371,23 @@ instance Eval a => EvalIO (PureEval a) where
369371
-- implement 'withAltering' and 'unsafeSpanBenign'. This is what the (admittedly
370372
-- poorly named) 'EvalM' class lets monad do.
371373
class EvalM m where
372-
withAlteringM :: Eval b => Field a -> (Maybe a -> Maybe a) -> m b -> m (Result b)
373-
unsafeSpanBenignM :: Eval a => IO () -> IO () -> m a -> m (Result a)
374+
spliceEval :: Eval b => (forall a. Eval a => (a -> Result a)) -> m b -> m (Result b)
375+
376+
withAlteringM :: (EvalM m, Eval b) => Field a -> (Maybe a -> Maybe a) -> m b -> m (Result b)
377+
withAlteringM f g = spliceEval (withAltering f g)
374378

375379
withSettingM :: (EvalM m, Eval b) => Field a -> a -> m b -> m (Result b)
376380
withSettingM f a = withAlteringM f (\_ -> Just a)
377381

382+
unsafeSpanBenignM :: (EvalM m, Eval a) => IO () -> IO () -> m a -> m (Result a)
383+
unsafeSpanBenignM before after = spliceEval (unsafeSpanBenign before after)
384+
378385
instance EvalM Identity where
379-
withAlteringM :: forall b a. Eval b => Field a -> (Maybe a -> Maybe a) -> Identity b -> Identity (Result b)
380-
withAlteringM = coerce $ withAltering @b @a
381-
unsafeSpanBenignM :: forall a. Eval a => IO () -> IO () -> Identity a -> Identity (Result a)
382-
unsafeSpanBenignM = coerce $ unsafeSpanBenign @a
386+
spliceEval :: forall b. Eval b => (forall a. Eval a => a -> Result a) -> Identity b -> Identity (Result b)
387+
spliceEval f = coerce $ f @b
383388

384389
instance (EvalM m, Eval s, Result s ~ s) => EvalM (StateT s m) where
385-
withAlteringM f g (StateT thing) = StateT $ \s -> withAlteringM f g (thing s)
386-
387-
unsafeSpanBenignM :: (EvalM m, Eval s, Result s ~ s, Eval a) => IO () -> IO () -> StateT s m a -> StateT s m (Result a)
388-
unsafeSpanBenignM before after (StateT thing) = StateT $ \s -> unsafeSpanBenignM before after (thing s)
390+
spliceEval f (StateT thing) = StateT $ \s -> spliceEval f (thing s)
389391

390392
instance (EvalM m) => EvalM (ReaderT e m) where
391-
withAlteringM f g (ReaderT thing) = ReaderT $ \e -> withAlteringM f g (thing e)
392-
393-
unsafeSpanBenignM before after (ReaderT thing) = ReaderT $ \e -> unsafeSpanBenignM before after (thing e)
393+
spliceEval f (ReaderT thing) = ReaderT $ \e -> spliceEval f (thing e)

0 commit comments

Comments
 (0)