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
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.
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:
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).
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With