haskellquasiquotes

How can I get the string of Haskell code (along with the value)


I'd like to get both the string and value of arbitrary Haskell code. For example:

f (1+1) -> (2,"1+1")

The reason I want to do this is because I'm writing a programming language and I'd like to provide an option to interpret the code (for fast running, i.e. scripting) or compile it to Haskell code (for efficient runtime). So for each builtin I only want to provide the implementation once. That is I don't want to say

plusop = ((+),"(+)")

I have some ideas involving reading the raw haskell source or a separate script that generates a compiler, but these seem much less elegant that what would be done if this question is possible.

It looks like QuasiQuotation could make this possible, but I can't figure out how to get the Haskell value of the expression if I use it (I can only get the String).

Is it possible? How can it be done?


Solution

  • I don't know exactly what you want to do, but here's an example of using Template Haskell to do something similar to your example:

    -- TH.hs
    {-# LANGUAGE TemplateHaskell #-}
    module TH where
    
    import Language.Haskell.TH.Syntax
    import Language.Haskell.TH.Ppr
    
    showAndRun :: Q Exp -> Q Exp
    showAndRun m = do
      x <- m
      let s = pprint x
      [| ($m, s) |]
    
    -- Main.hs
    {-# LANGUAGE TemplateHaskell #-}
    import TH
    
    main :: IO ()
    main = print $(showAndRun [| 1 + 1 |])
    
    $ runhaskell Main.hs
    (2,"1 GHC.Num.+ 1")
    

    I don't know how to pretty print the expression without the qualified GHC.Num prefix. You could try copying the implementation of Language.Haskell.TH.Ppr and change it in the necessary places. Or the easiest is perhaps just a post-processing step where you strip each word that starts with a capital letter and ends in a ..