4

The type of (forward) rewriting functions in Hoopl is given by the mkFRewrite function:

mkFRewrite :: (FuelMonad m) => 
   (forall e x.
      n e x
      -> f
      -> m (Maybe (hoopl-3.8.6.1:Compiler.Hoopl.Dataflow.Graph n e x)))
   -> FwdRewrite m n f

The m type implies that I can use monadic effects while rewriting. The paper "Hoopl: A Modular, Reusable Library for Dataflow Analysis and Transformation" says the same in Section 4.3, "The rewrite function and the client's monad."

Can anyone give me an example of a rewrite function that has non-Hoopl monadic effects embedded inside it? For example, a rewriter that uses a State monad or does some IO.

sth
  • 222,467
  • 53
  • 283
  • 367
Justin Bailey
  • 1,487
  • 11
  • 15
  • 1
    As discussed in the previous question, FuelMonad is opaque: http://stackoverflow.com/questions/6495320/hoopl-how-can-i-combine-the-checkingfuelmonad-with-a-state-monad -- I think at this point its worth writing the authors of Hoopl directly. I suspect that they hid more than they intended, and so restricted more functionality than thy realized. – sclv Jul 01 '11 at 16:12
  • That was my suspicion as well. – Justin Bailey Jul 01 '11 at 16:49
  • The first listed author (and package maintainer) for Hoopl has [a significant presence on SO](http://stackoverflow.com/users/41661/norman-ramsey), so I'm actually surprised he hasn't responded to these questions about it. Though it does look like he's been less active recently... – C. A. McCann Jul 01 '11 at 19:16

1 Answers1

2

This should be pretty simple, just chase the types.

You want a value of FwdRewrite m n f with a custom value of m, so you can pass it to the following function:

analyzeAndRewriteFwd ::
  forall m n f e x entries.
    (CheckpointMonad m,
     NonLocal n,
     LabelsPtr entries) =>
  FwdPass m n f ->
  MaybeC e entries ->
  Graph n e x ->
  Fact e f ->
  m (Graph n e x, FactBase f, MaybeO x f)

So the only constraint on m you have is that it is a CheckpointMonad; then when you run the pass you'll get the final monadic value which you can run yourself.

In fact, GHC's Hoopl passes use with m as a SimplUniqMonad, so we can get fresh labels while we're operating on the graph.

{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE TypeFamilies #-}

import Compiler.Hoopl
import Control.Monad.State

type StateFuel s a = CheckingFuelMonad (State s) a

instance CheckpointMonad (State s) where
    type Checkpoint (State s) = s
    checkpoint = get
    restart = put
Edward Z. Yang
  • 26,325
  • 16
  • 80
  • 110
  • Thanks for answering, but I want to see non-Hoopl monadic effects inside the rewrite function. I think the best your example can show is using `checkpoint` and `restart,` both Hoopl-provided functions. – Justin Bailey Jul 05 '11 at 15:38
  • 1
    Justin: I still don't understand: are you looking for situations in which non-Hoopl monadic actions are appropriate? (Here's a super easy one: unique name generation) or how to actually, technically speaking, do it (which is pretty trivial, because the output of the rewrite function is a *monadic action*). Note that using the checkpoint functions is a bad idea, since Hoopl uses those to preserve determinacy while calculating fixpoints. – Edward Z. Yang Jul 08 '11 at 12:17
  • I would like to see how to do it. I think you can't implement any because the `FuelMonad` class' members are hidden, but I would **love** to be proved wrong. If you know of code examples, please point them out! – Justin Bailey Jul 11 '11 at 19:50
  • 1
    Looks like you are right. You can, technically speaking, put your own monad to be used, but you can't access any of its special features, since the only two instances of FuelMonad have no MonadTrans instance. – Edward Z. Yang Jul 16 '11 at 03:37