About MonadTransControl and MonadBaseControl for monad-control

Asked 2 years ago, Updated 2 years ago, 89 views

There are MonadTransControl and MonadBaseControl in the monad-control package, but what is the correct way to use them?
http://maoe.hatenadiary.jp/entry/20111207/1323185162

for

Simply put, the MonadTransControl class liftWith::Monadm=>(Run->ma)->
tma is the type m
that pop one monad stack tma It has a role to play with a, and MonadBaseControl's liftBaseWith::(RunInBase mb->b
) a) ->ma has a role to play with the base monad type ba that pops to the bottom of the stack.

It says, but both had to be lifted to the bottom.
Is MonadTransControl an aid in defining MonadBaseControl?

 {-#LANGUAGE ScopedTypeVariables#-}
{-# LANGUAGE DeriveDataType#-}
{-# LANGUAGE FlexibleContexts#-}
{-# LANGUAGE FlexibleInstances#-}
{-# LANGUAGE GeneralizedNewtypeDeriving#-}
{-# LANGUAGE MultiParamTypeClasses#-}
{-# LANGUAGE StandaloneDeriving#-}
{-# LANGUAGE TypeFamilies#-}
{-# LANGUAGE UndecidableInstances#-}

import Control.Monad.Base
import Control.Monad.Reader
import Control.Monad.State
import Control.Applicative
import Control.Monad.Trans.Control
import Control.Monad.Identity
import Control.Monad.Except
import Control.Monad.Trans.Except
import Data.Maybe
import qualified Data.Map as Map

typeName = String
type Value = String
typeEnv = Map.MapNameValue
-- Inside the EvalR
newtypeEvalEma=EvalE{runEvalE::ExceptT Stringma}
  deriving (Functor)
          , Applicative
          , Monad
          , MonadError String
          , MonadBase base
          )
instanceMonadTransEvalEwhere
  lift = EvalE.lift

instanceMonadTransControlEvalEwhere
  type StT EvalEa = StT(ExceptT String)a
  liftWith=defaultLiftWithEvalErunEvalE
  restoreT=defaultRestoreTEvalE

instance(MonadBaseControl bm) =>MonadBaseControl b(EvalEm)where
  typeStM(EvalEm)a=ComposeStEvalEma
  liftBaseWith=defaultLiftBaseWith
  restoreM=defaultRestoreM
evalET::(Monad(t[], MonadTransControlt) =>t[] Int
evalET = return1
EVALEM::(MonadBaseControl[] m) =>m Int
eventEM=return1

doEvalET::EvalE[] Int->EvalE[] Int
doEvalETt=liftWith(\run->run)>>=restoreT.return
doEvalEM::EvalE[] Int->EvalE[] Int
doEvalEMm=liftBaseWith(\run->runm)>>=restoreM

exEvalE::EvalE[] Int->IO()
exEvalE=print.runEvalE
exEvalET::EvalE[] Int->IO()
exEvalET=print.runEvalE.doEvalET
exEvalEM::EvalE[] Int->IO()
exEvalEM=print.runEvalE.doEvalEM

newtypeEvalRma=EvalR{runEvalR::ReaderTEnv(EvalEm)a}
  deriving (Functor)
          , Applicative
          , Monad
          , MonadError String
          , MonadReader Env
          , MonadBase base
          )
instanceMonadTransEvalRwhere
  lift = EvalR.lift.lift

-- I had to lift everything.
-- In fact, I picked up just one thing, and it turned out to be EvalE.
instanceMonadTransControlEvalRwhere
  type StTEvalRa=StTEvalE(StT(ReaderTEnv)a)
  liftWith=EvalR$liftWith$\runReader->
                          liftWith$\runEval->
                            f$runEval.runReader.runEvalR
  restoreT=EvalR.restoreT.restoreT

instance(MonadBaseControl bm) =>MonadBaseControl b(EvalRm)where
    typeStM(EvalRm)a=ComposeStEvalRma
    liftBaseWith=defaultLiftBaseWith
    restoreM=defaultRestoreM

env::Env
env=Map.fromList [("0", "zero"), (1", "one")]

doEvalRT::EvalR[]Int->EvalR[]Int
doEvalRTt=do
    x<-liftWith$\r->
      rt
    restoreT$returnx
doEvalRM::EvalR[]Int->EvalR[]Int
doEvalRMm=liftBaseWith(\run->runm)>>=restoreM

exEvalR::EvalR[]Int->IO()
exEvalR=print.runEvalE.(flip runReaderTenv).runEvalR
exEvalRT::EvalR[]Int->IO()
exEvalRT=print.runEvalE.(flip runReaderTenv).runEvalR.doEvalRT
exEvalRM::EvalR[]Int->IO()
exEvalRM=print.runEvalE.(flip runReaderTenv).runEvalR.doEvalRM

Or is it possible to use the different types of tma and ma?

maybeTIO::(Monad(tIO), MonadTransControlt) =>t IO Int
maybeTIO=lift(putStrLn "testMaybeT")>>return1
maybeMIO::(MonadBaseControl IOm) =>m Int
maybeMIO=liftBase(putStrLn "testMaybeT")>>return1

twiceIO::IO a->IO a
twiceIO action=action>>action

testLiftWith::MaybeTIO Int ->MaybeTIO Int
testLiftWith=liftWith(\run->twiceIO(runf))>>=restoreT.return
testLiftBaseWith::MaybeTIO Int ->MaybeTIO Int
testLiftBaseWith=liftBaseWith(\run->twiceIO(runf))>>=restoreM
testControl::MaybeTIO Int->MaybeTIO Int
testControlf=control(\run->twiceIO(runmaybeTIO))

haskell

2022-09-29 21:58

1 Answers

In the example presented, two layers of monad stack called MaybeTIO are used, so MonadTransControl and MonadBaseControl are lifted the same, but using more than three layers of stack makes the difference.

The following example uses a three-tier stack called StateT Int (MaybeTIO).In this case, the testLiftBaseWith2 using MonadBaseControl automatically lifts two tiers, so the testLiftBaseWith code can be used as it is.On the other hand, in testLiftWith2 using MonadTransControl, one liftWith lifts only one tier and must be lifted twice explicitly.

testLiftWith2::StateT Int (MaybeTIO) Int->StateT Int (MaybeTIO) Int
testLiftWith2f=liftWith(\runState->liftWith(\runMaybe->twiceIO(runMaybe(runMaybe(runStatef))))>=restoreT.return)>=restoreT.return

testLiftBaseWith2::StateT Int (MaybeTIO) Int->StateT Int (MaybeTIO) Int
testLiftBaseWith2f = liftBaseWith(\run->twiceIO(runf))>>=restoreM

While MonadTrans lifts only one layer, MonadIO lifts the bottom layer of MonadIO lifts the bottom layer of IO (MonadBase can also be used to generalize MonadI).


2022-09-29 21:58

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.