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 pape开发者_开发知识库r "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.
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
精彩评论