[英]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
.换句话说,您不能在参数中使用
InterpreterMT
来lift
.
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 is而
interpreter
返回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.