7

我正在使用Hoopl库,并希望在重写时携带一些状态。重写函数对于所使用的 monad 是多态的,但我无法弄清楚如何将Statemonad 与库的 monad 之一结合起来Fuel

下面是一个最小的例子。MyMonad是 Hoopl'sCheckingFuelMonadState携带旗帜的单子的同义词。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正确编写函数?

4

2 回答 2

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
于 2011-06-27T16:24:43.027 回答
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本身就是 a Monad,尽管CheckingFuelMonad它似乎没有被定义为一个单子转换器,所以你只有一个单子层return

于 2011-06-27T16:29:06.193 回答