Search code examples
haskellcompiler-constructionmonadsdataflowhoopl

Examples of monadic effects inside a rewrite function in Hoopl?


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.


Solution

  • 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