Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Print and execute a string

I find myself writing a lot of code like

putStr "foo (bar 1) (bar 2) ="
print $ foo (bar 1) (bar 2)

The trouble is, the printed message can get out of sync with the actual executed code. The obvious solution is to auto-generate this code.

One way to do that would be to put all the text in a file, and write a small program that reads the file and generates Haskell source code from it. But another alternative is to use Template Haskell.

Does anybody know how I would go about writing a function that takes a String and generates the above code from it? I'm guessing it should be pretty easy, but TH is not well documented.

like image 598
MathematicalOrchid Avatar asked Feb 29 '12 11:02

MathematicalOrchid


People also ask

How do you execute a string?

Given few lines of code inside a string variable and execute the code inside the string. Examples: Input: code = """ a = 6+5 print(a)""" Output: 11 Explanation: Mind it that "code" is a variable and not python code.

How do you execute a string in Python?

If you want to execute Python statements, you can use exec(string). For example, >>> my_code = 'print "Hello World!"' >>> exec(my_code) Hello World!

Can you print a string in Python?

How to print a variable and a string in Python by separating each with a comma. You can print text alongside a variable, separated by commas, in one print statement. In the example above, I first included some text I wanted to print in double quotation marks – in this case, the text was the string Hello .

What is the use of print () method?

print(): print() method in Java is used to display a text on the console. This text is passed as the parameter to this method in the form of String. This method prints the text on the console and the cursor remains at the end of the text at the console.


2 Answers

You can parse Haskell code using the haskell-src-meta package. Here's a quick example how you could combine this with Template Haskell.

{-# LANGUAGE TemplateHaskell #-}

import Language.Haskell.TH
import Language.Haskell.TH.Quote
import Language.Haskell.Meta

runShow = QuasiQuoter
    { quoteExp  = runShowQQ
    , quotePat  = undefined
    , quoteType = undefined
    , quoteDec  = undefined
    }

runShowQQ :: String -> Q Exp
runShowQQ s = do
    let s'          = s ++ " = "
        Right exp = parseExp s
        printExp  = appE [|print|] (return exp)
    infixApp [|putStr s'|] [|(>>)|] printExp

And you would use it like this

{-# LANGUAGE QuasiQuotes #-}

[runShow|foo (bar 1) (bar 2)|]
like image 113
shang Avatar answered Sep 23 '22 14:09

shang


Template Haskell does not provide a straightforward means of parsing arbitrary strings, so the simplest solution is probably to use the C preprocessor. However, the built-in one in GHC does not support stringification, so we need to pass extra options to use the "real" one instead.

{-# LANGUAGE CPP #-}
{-# OPTIONS_GHC -pgmP cpp #-}

#define PRINT_EXP(x) (putStr #x >> putStr " = " >> print (x))

You can then use it like this:

PRINT_EXP(foo (bar 1) (bar 2))
like image 41
hammar Avatar answered Sep 22 '22 14:09

hammar