Search code examples
haskellmonadsstate-monadhoopl

How can I combine the CheckingFuelMonad with a State monad in Hoopl?


I am using the Hoopl library and would like to carry some state around while rewriting. The rewrite functions are polymorphic regarding the monad used, but I cannot figure out how to combine a State monad with one of the library's Fuel monads.

Below is a minimal example. MyMonad is a synonym combining Hoopl's CheckingFuelMonad and a State monad carrying a flag. Stmt is just a placeholder for my intermediate language and isn't really important.

{-# 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

But this will not compile -- GHC complains that rewrite has the wrong type:

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)))

Is what I want to do possible? How can I write the rewrite function correctly?


Solution

  • A browse through hoopl code reveals that CheckingFuelMonad isn't an instance of MonadTrans, and you can't make it one, since its constructors are not exported. You can however wrap a StateT around CheckingFuelMonad, like so:

    {-# 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