简体   繁体   English

哈斯克尔。 提升 monad 错误和本地功能

[英]Haskell. Lifting monad Error and local function

    data InterpreterM a = ExeInterpreter a | PropInterpreter a

    newtype InterpreterMT m a = InterpreterMT { runInterpreterMT :: m (InterpreterM a) }

    type Interpreter = InterpreterMT (StateT Int (ReaderT Int (ErrorT String IO)))
    data Stmts = Statements Stmt Stmts | EmptyStmts


  instance (Monad m) => Monad (InterpreterMT m) where
        return x = InterpreterMT $ return (ExeInterpreter x)
        x >>= f = InterpreterMT $ do
            m <- runInterpreterMT x 
            case m of
                (ExeInterpreter a) -> runInterpreterMT (f a)
    interpreter :: Stmts -> Interpreter ()
    interpreter EmptyStmts = return () 
    interpreter (Statements s stmts) = lift $ local (\x -> x) (interpreter stmts)





instance MonadTrans InterpreterMT where
    lift m = InterpreterMT $ do
        x <- m
        return $ ExeInterpreter x

Compiler gives me erorr in last line:编译器在最后一行给了我错误:

  Couldn't match type `InterpreterMT
                           (StateT Int (ReaderT Int (ErrorT String IO)))'
                  with `StateT Int (ReaderT Int (ErrorT String IO))'
    Expected type: Interpreter ()
      Actual type: InterpreterMT
                     (InterpreterMT (StateT Int (ReaderT Int (ErrorT String IO)))) ()
    In the expression: lift $ local (\ x -> x) (interpreter stmts)
    In an equation for `interpreter':
        interpreter (Statements s stmts)
          = lift $ local (\ x -> x) (interpreter stmts)

How to repair it and why it is an error?如何修复它以及为什么它是一个错误?

Okay, two problems.好吧,两个问题。

First, lift has the following signature:首先, lift具有以下签名:

lift :: (MonadTrans t, Monad m) => m a -> t m a

So you have to supply non-transformed monadic action to lift.所以你必须提供非转换的 monadic action 来提升。 In other words, you can't use InterpreterMT in an argument to lift .换句话说,您不能在参数中使用InterpreterMTlift .

So you would need to unwrap it:所以你需要解开它:

lift $ local id $ runInterpreterMT $ interpreter stmts

But now your return types don't make sense: runInterpreterMT $ ... has type但现在你的返回类型没有意义: runInterpreterMT $ ...有类型

StateT Int (ReaderT Int (ErrorT String IO)) (InterpreterM ())

or, shortening transformer stack to M ,或者,将变压器组缩短为M

M (InterpreterM ())

while interpreter returns Interpreter () , which isinterpreter返回Interpreter () ,即

InterpreterMT (StateT Int (ReaderT Int (ErrorT String IO))) ()

or, shortening transformer stack,或者,缩短变压器组,

InterpreterMT M ()

going back to type of lift , ma -> tma becomes M (InterpreterM ()) -> InterpreterMT M (InterpreterM ()) .回到lift类型, ma -> tma变成M (InterpreterM ()) -> InterpreterMT M (InterpreterM ()) (InterpreterM ()) is not () . (InterpreterM ())不是()

The root of the problem?问题的根源? Your InterpreterMT is not actually a monad transformer, since it doesn't really transform the monad.您的InterpreterMT实际上并不是一个 monad 转换器,因为它并没有真正转换 monad。 It transforms the value.它改变了价值。

Easy fix?容易修吗? Provided that you can figure out a reasonable Monad instance for InterpreterMT (one you provided is doubtful), you can define a MonadReader instance for InterpreterMT :假设您可以为InterpreterMT找出一个合理的Monad实例(您提供的一个值得怀疑),您可以为InterpreterMT定义一个MonadReader实例:

instance MonadReader r m => MonadReader r (InterpreterMT m) where
  local f = InterpreterMT . local f . runInterpreterMT
  ...

(you'll need UndecideableInstances for this particular definition) (对于这个特定的定义,你需要UndecideableInstances

General pattern seems to be一般模式似乎是

inInterpreter f = InterpreterMT . f . runInterpreterMT

Note that this is not a Functor .请注意,这不是Functor

Not sure what you want to achieve here, but this whole design seems... underdeveloped.不确定你想在这里实现什么,但整个设计似乎......不发达。 Maybe it's a good idea to go back to drawing board and figure out what exactly you want your architecture to be like.也许回到绘图板并弄清楚你想要你的架构到底是什么样子是个好主意。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM