如何将CheckingFuelMonad与Hoopl中的State monad结合使用?

Jus*_*ley 7 monads haskell state-monad hoopl

我正在使用Hoopl库,并希望在重写时携带一些状态.关于使用的monad,重写函数是多态的,但我无法弄清楚如何将Statemonad与库的Fuelmonad组合.

以下是一个最小的例子.MyMonad是Hoopl CheckingFuelMonadState携带旗帜的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
Run Code Online (Sandbox Code Playgroud)

但这不会编译 - 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)))
Run Code Online (Sandbox Code Playgroud)

我想做什么?如何rewrite正确编写函数?

scl*_*clv 4

浏览 hoopl 代码会发现 CheckingFuelMonad 不是 MonadTrans 的实例,并且您不能将其设为实例,因为它的构造函数未导出。但是,您可以将 StateT 包裹在 CheckingFuelMonad 周围,如下所示:

{-# 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
Run Code Online (Sandbox Code Playgroud)