Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I create a function at runtime by evaluating a string?

Tags:

haskell

eval

In my program for solving discrete maths, I want to let the user input a string of logic operations; e.g., if the user inputs let f (x:y:_) = x && y, then I would get a function f for use in the rest of the program. In GHCi, I can easily test my program by inputting let f (x:y:_) = x && y.

I have no idea how to achieve this task. I have taken a look into the eval function from the plugins package, but it seems not to be the right function. Can I do this in Haskell?

The code I'm planning to use this with is:

type TruthTable = [[Bool]]
type TruthTableResult = [([Bool], Bool)]

solveTable :: ([Bool] -> Bool) -> Integer -> (TruthTableResult)
solveTable f n = let table = truthTable n
                     result = map f table
                 in  zipWith (\v r -> (v, r)) table result
like image 938
code4j Avatar asked Sep 16 '13 05:09

code4j


3 Answers

There is no standard Haskell function, because Haskell is complied, not interpreted. However, there are libraries that allow you to read and compile Haskell code at run time. One of them is hint. Example for your case:

import Control.Monad
import Language.Haskell.Interpreter

main = do
    -- fExpr is a Haskell code supplied by your user as a String
    let fExpr = "let f (x:y:_) = x && y in f"
    -- Create an interpreter that runs fExpr
    r <- runInterpreter $ do
            setImports ["Prelude"]
            interpret fExpr (const True :: [Bool] -> Bool)
    -- run it and get an interface to the function
    case r of
        Left err -> putStrLn $ "Ups... " ++ (show err)
        Right f  -> do
            print $ f [True, False]
            print $ f [True, True]

More examples available here.

like image 72
Petr Avatar answered Sep 20 '22 19:09

Petr


You are writing an eval function - a form of runtime metaprogramming.

eval :: String -> a

If the string represents a Haskell program, then you must parse the string, type check it, and then compile it to a target interpreter or runtime. This requires access to the compiler as a library, either exported as a runtime service (in an interpreter) or as a separate package (as for a compiler).

The GHC implementation of Haskell has several libraries for doing runtime evaluation of Haskell code:

  • via the GHCi interpreter- hint
  • via the compiler - plugins

These apply only if your input language is Haskell.

If instead your input string represents a program in some other language, then you are looking for a DSL interpreter. This can be done by writing your own interpreter for the input language (or reusing a library if it is a common language).

like image 34
Don Stewart Avatar answered Sep 19 '22 19:09

Don Stewart


The short answer is that Haskell has no "eval" function, unlike interpreted languages which can do this quite easily (after all, they have the interpreter handy and already running).

You can include the Haskell compiler as a library: see http://www.haskell.org/haskellwiki/GHC/As_a_library. This is the nearest thing to what you ask for.

However it sounds like you don't want the whole of Haskell here; what you are really want is a different language which may have Haskell-like syntax but is not the whole of Haskell. If so then the real solution is to define that language and write a parser for it. The Parsec library is the place to start for that.

like image 40
Paul Johnson Avatar answered Sep 19 '22 19:09

Paul Johnson