我可以通过评估字符串在运行时创建函数吗?

时间:2013-09-16 05:44:59

标签: haskell eval

在我解决离散数学的程序中,我想让用户输入一串逻辑运算; 例如,如果用户输入let f (x:y:_) = x && y,那么我会得到一个函数f,用于该程序的其余部分。在GHCi中,我可以通过输入let f (x:y:_) = x && y轻松测试我的程序。

我不知道如何完成这项任务。我查看了plugins包中的eval函数,但它似乎不是正确的函数。我可以在Haskell中这样做吗?

我计划使用的代码是:

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

3 个答案:

答案 0 :(得分:15)

没有标准的Haskell函数,因为Haskell是编译的,而不是解释的。但是,有些库允许您在运行时读取和编译Haskell代码。其中一个是hint。案例:

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]

更多可用示例here

答案 1 :(得分:10)

您正在编写eval函数 - 一种运行时元编程形式。

eval :: String -> a

如果字符串表示Haskell程序,则必须解析字符串,键入check it,然后将其编译为目标解释器或运行时。这需要将编译器作为库访问,可以作为运行时服务(在解释器中)导出,也可以作为单独的包导出(对于编译器)。

Haskell的GHC实现有几个用于对Haskell代码进行运行时评估的库:

仅当您的输入语言是Haskell时才适用。

如果您的输入字符串代表某种其他语言的程序,那么您正在寻找DSL解释器。这可以通过为输入语言编写自己的解释器来完成(或者如果它是一种通用语言则重用库)。

答案 2 :(得分:5)

简短的回答是Haskell没有“eval”功能,不像解释语言可以很容易地做到这一点(毕竟,他们有解释器方便且已经运行)。

您可以将Haskell编译器包含为库:请参阅http://www.haskell.org/haskellwiki/GHC/As_a_library。这是你要求的最接近的东西。

然而,听起来你并不想要整个Haskell;你真正想要的是一种不同的语言,它可能具有类似Haskell的语法,但不是整个Haskell。如果是这样,那么真正的解决方案是定义该语言并为其编写解析器。 Parsec库是开始的地方。