我正在使用Hoopl库,并希望在重写时携带一些状态。重写函数对于使用的monad是多态的,但我无法弄清楚如何将State
monad与库的Fuel
monad组合。
以下是一个最小的例子。 MyMonad
是Hoopl的CheckingFuelMonad
和携带旗帜的State
monad的同义词。 Stmt
只是我的中间语言的占位符,并不重要。
{-# LANGUAGE GADTs, RankNTypes #-}
import Compiler.Hoopl
import Control.Monad.State
type MyMonad = CheckingFuelMonad (State Bool)
data Stmt e x where
Bind :: () -> Stmt O O
rewriter :: forall e x. Stmt e x -> Fact x () -> MyMonad (Maybe (Graph Stmt e x))
rewriter (Bind ()) () = return $ do
f <- get
if f
then return $ Just emptyGraph
else return Nothing
但这不会编译 - GHC抱怨rewrite
的类型错误:
Couldn't match expected type `Graph' Block Stmt e x'
against inferred type `Maybe (g n O O)'
Expected type: CheckingFuelMonad
(State Bool) (Maybe (Graph Stmt e x))
Inferred type: CheckingFuelMonad
(State Bool) (Maybe (Maybe (g n O O)))
我想做的是什么?如何正确编写rewrite
函数?
答案 0 :(得分:4)
浏览hoopl代码显示,CheckingFuelMonad不是MonadTrans的实例,并且您不能将其设置为一个,因为它的构造函数不会导出。你可以然后在CheckingFuelMonad周围包装一个StateT,如下所示:
{-# LANGUAGE GADTs, RankNTypes #-}
import Compiler.Hoopl
import Control.Monad.State
type MyMonad = StateT Bool SimpleFuelMonad
data Stmt e x where
Bind :: () -> Stmt O O
rewriter :: forall e x. Stmt e x -> Fact x () -> MyMonad (Maybe (Graph Stmt e x))
rewriter (Bind ()) () = do
f <- get
if f
then return $ Just emptyGraph
else return Nothing
答案 1 :(得分:1)
那么,您当前错误的直接原因很简单。如果f
为真,最终表达式是什么?如果我们接受这个:
rewriter :: forall e x. Stmt e x -> Fact x () -> MyMonad (Maybe (Graph Stmt e x))
rewriter (Bind ()) () = return $ do
f <- get
if f
then return $ Just emptyGraph
else return Nothing
...除去我们得到的True
分支以外的所有内容:
rewriter :: forall e x. Stmt e x -> Fact x () -> MyMonad (Maybe (Graph Stmt e x))
rewriter (Bind ()) () = return $ do
return $ Just emptyGraph
...简化为:
rewriter :: forall e x. Stmt e x -> Fact x () -> MyMonad (Maybe (Graph Stmt e x))
rewriter (Bind ()) () = return $ return $ Just emptyGraph
return $ return $ Just emptyGraph
的类型是什么?
(Monad m1, Monad m2, GraphRep g) => m1 (m2 (Maybe (g n O O)))
换句话说,你在那里有一个额外的return
。 (Monad m) => CheckingFuelMonad m
本身就是Monad
,即使CheckingFuelMonad
似乎没有被定义为monad变换器,所以你只有一个monad层到return
。