heftia-0.1.0.0: src/Control/Monad/Trans/Heftia.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 Heftia monad transformers.
-}
module Control.Monad.Trans.Heftia where
import Control.Effect.Class (Signature, type (~>))
import Control.Effect.Class.Machinery.HFunctor (HFunctor)
import Control.Heftia.Trans (TransHeftia, elaborateHT, hoistHeftia, liftLowerHT)
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 Heftia monad transformers.
class
(TransHeftia Monad h, forall sig. HFunctor sig => MonadTrans (h sig)) =>
MonadTransHeftia h
where
elaborateMK ::
(Monad m, HFunctor sig) =>
(sig (ContT r m) ~> ContT r m) ->
h sig m ~> ContT r m
elaborateMK = elaborateMT
{-# INLINE elaborateMK #-}
reelaborateMK ::
(Monad m, HFunctor sig) =>
(sig (ContT r (h sig m)) ~> ContT r (h sig m)) ->
h sig m ~> ContT r (h sig m)
reelaborateMK = reelaborateMT
{-# INLINE reelaborateMK #-}
elaborateMT ::
(Monad m, MonadTrans t, Monad (t m), HFunctor sig) =>
(sig (t m) ~> t m) ->
h sig m ~> t m
elaborateMT = elaborateHT lift
{-# INLINE elaborateMT #-}
reelaborateMT ::
forall m t n sig.
(Monad m, MonadTrans t, Coercible n (h sig m), Monad (t n), Monad n, HFunctor sig) =>
(sig (t n) ~> t n) ->
h sig m ~> t n
reelaborateMT f = elaborateMT f . hoistHeftia (coerce . liftLowerHT @Monad @h @sig)
{-# INLINE reelaborateMT #-}
reinterpretHTTViaFinal ::
forall h m t n sig.
( MonadTransHeftia h
, Monad m
, MonadTrans t
, Coercible n (h sig m)
, Monad (t n)
, Monad n
, HFunctor sig
) =>
(sig (t n) ~> t n) ->
h sig m ~> t n
reinterpretHTTViaFinal = elaborateHT $ lift . coerce . liftLowerHT @Monad @h @sig
{-# INLINE reinterpretHTTViaFinal #-}
newtype ViaLiftLowerH (h :: Signature -> (Type -> Type) -> Type -> Type) sig m a = ViaLiftLowerH
{runViaLiftLowerH :: h sig m a}
deriving newtype (Functor, Applicative, Monad)
deriving stock (Foldable, Traversable)
instance (TransHeftia Monad h, HFunctor sig) => MonadTrans (ViaLiftLowerH h sig) where
lift = ViaLiftLowerH . liftLowerHT
{-# INLINE lift #-}