cloudchor-0.1.0.1: src/Control/Monad/Freer.hs
-- SPDX-FileCopyrightText: 2022 Gan Shen
-- SPDX-FileCopyrightText: 2025 Alex Ionescu
-- SPDX-License-Identifier: MPL-2.0 AND BSD-3-Clause
-- | This module defines the freer monad `Freer`, which allows manipulating
-- effectful computations algebraically.
module Control.Monad.Freer where
import Control.Monad ((>=>))
-- | Freer monads.
--
-- A freer monad @Freer f a@ represents an effectful computation that returns a
-- value of type @a@. The parameter @f :: * -> *@ is a effect signature that
-- defines the effectful operations allowed in the computation. @Freer f a@ is
-- called a freer monad in that it's a `Monad` given any @f@.
data Freer f a where
-- | A pure computation.
Return :: a -> Freer f a
-- | An effectful computation where the first argument @f b@ is the effect
-- to perform and returns a result of type @b@; the second argument
-- @b -> Freer f a@ is a continuation that specifies the rest of the
-- computation given the result of the performed effect.
Do :: f b -> (b -> Freer f a) -> Freer f a
instance Functor (Freer f) where
fmap f (Return a) = Return (f a)
fmap f (Do eff k) = Do eff (fmap f . k)
instance Applicative (Freer f) where
pure = Return
(Return f) <*> a = fmap f a
(Do eff k) <*> a = Do eff $ (<*> a) . k
instance Monad (Freer f) where
(Return a) >>= f = f a
(Do eff k) >>= f = Do eff (k >=> f)
-- | Lift an effect into the freer monad.
toFreer :: f a -> Freer f a
toFreer eff = Do eff Return
-- | Interpret the effects in a freer monad in terms of another monad.
interpFreer :: Monad m => (forall a. f a -> m a) -> Freer f a -> m a
interpFreer _handler (Return a) = return a
interpFreer handler (Do eff k) = handler eff >>= interpFreer handler . k