heftia-0.1.0.0: src/Control/Monad/Trans/Freer.hs
{-# LANGUAGE QuantifiedConstraints #-}
-- This Source Code Form is subject to the terms of the Mozilla Public
-- License, v. 2.0. If a copy of the MPL was not distributed with this
-- file, You can obtain one at https://mozilla.org/MPL/2.0/.
{- |
Copyright : (c) 2023 Yamada Ryo
License : MPL-2.0 (see the file LICENSE)
Maintainer : ymdfield@outlook.jp
Stability : experimental
Portability : portable
A type class to abstract away the encoding details of the Freer monad transformers.
-}
module Control.Monad.Trans.Freer where
import Control.Effect.Class (Instruction, type (~>))
import Control.Freer.Trans (TransFreer, hoistFreer, interpretFT, liftLowerFT)
import Control.Monad.Cont (ContT)
import Control.Monad.Trans (MonadTrans, lift)
import Data.Coerce (Coercible, coerce)
import Data.Kind (Type)
-- | A type class to abstract away the encoding details of the Freer monad transformers.
class
(TransFreer Monad fr, forall ins. MonadTrans (fr ins)) =>
MonadTransFreer fr
where
interpretMK :: Monad m => (ins ~> ContT r m) -> fr ins m ~> ContT r m
interpretMK = interpretMT
{-# INLINE interpretMK #-}
reinterpretMK :: Monad m => (ins ~> ContT r (fr ins m)) -> fr ins m ~> ContT r (fr ins m)
reinterpretMK = reinterpretMT
{-# INLINE reinterpretMK #-}
interpretMT :: (Monad m, MonadTrans t, Monad (t m)) => (ins ~> t m) -> fr ins m ~> t m
interpretMT = interpretFT lift
{-# INLINE interpretMT #-}
reinterpretMT ::
forall m t n ins.
(Monad m, MonadTrans t, Coercible n (fr ins m), Monad (t n), Monad n) =>
(ins ~> t n) ->
fr ins m ~> t n
reinterpretMT f = interpretMT f . hoistFreer (coerce . liftLowerFT @Monad @fr @ins)
{-# INLINE reinterpretMT #-}
reinterpretTTViaFinal ::
forall fr m t n ins.
( MonadTransFreer fr
, Monad m
, MonadTrans t
, Coercible n (fr ins m)
, Monad (t n)
, Monad n
) =>
(ins ~> t n) ->
fr ins m ~> t n
reinterpretTTViaFinal = interpretFT $ lift . coerce . liftLowerFT @Monad @fr @ins
{-# INLINE reinterpretTTViaFinal #-}
newtype ViaLiftLower (fr :: Instruction -> (Type -> Type) -> Type -> Type) ins m a = ViaLiftLower
{runViaLiftLower :: fr ins m a}
deriving newtype (Functor, Applicative, Monad)
deriving stock (Foldable, Traversable)
instance TransFreer Monad h => MonadTrans (ViaLiftLower h ins) where
lift = ViaLiftLower . liftLowerFT
{-# INLINE lift #-}