9

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

我不知道如何完成这项任务。我已经从包中查看了eval函数plugins,但它似乎不是正确的函数。我可以在 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
4

3 回答 3

15

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

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]

此处提供更多示例。

于 2013-09-16T07:33:04.470 回答
10

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

eval :: String -> a

如果该字符串表示一个 Haskell 程序,那么您必须解析该字符串,对其进行类型检查,然后将其编译为目标解释器或运行时。这需要将编译器作为库访问,或者作为运行时服务(在解释器中)或作为单独的包(对于编译器)导出。

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

这些仅适用于您的输入语言是 Haskell。

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

于 2013-09-16T07:19:47.850 回答
5

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

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

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

于 2013-09-16T06:26:32.253 回答