Haskell 我可以通过计算字符串在运行时创建函数吗?

Haskell 我可以通过计算字符串在运行时创建函数吗?,haskell,eval,Haskell,Eval,在我求解离散数学的程序中,我想让用户输入一系列逻辑运算;e、 例如,如果用户输入let f(x:y:)=x&&y,那么我将获得一个函数f,用于程序的其余部分。在GHCi中,我可以通过输入let f(x:y:ux)=x&&y轻松测试我的程序 我不知道如何完成这项任务。我已经从插件包中查看了该函数,但它似乎不是正确的函数。我能在Haskell做这个吗 我计划使用的代码是: type TruthTable = [[Bool]] type TruthTableResult = [([Bool], Boo

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

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

简单的回答是Haskell没有“eval”函数,这与解释语言不同,解释语言可以很容易地做到这一点(毕竟,他们手边有解释器并且已经在运行)

可以将Haskell编译器作为库包括在内:请参阅。这是最接近你要求的东西


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

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

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

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

  • 通过GHCi口译员-
  • 通过编译器-
仅当您的输入语言为Haskell时,这些选项才适用


如果您的输入字符串表示其他语言的程序,那么您正在寻找DSL解释器。这可以通过为输入语言编写自己的解释器来实现(如果它是公共语言,也可以重用库)。

没有标准的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]
import-Control.Monad
导入Language.Haskell.Interpreter
main=do
--fExpr是用户以字符串形式提供的Haskell代码
let-fExpr=“let f(x:y:2;)=f中的x&&y”
--创建一个运行fExpr的解释器
r(布尔)
--运行它并获得函数的接口
案例r
左错误->putStrLn$“Ups…”++(显示错误)
右f->do
打印$f[正确,错误]
打印$f[正确,正确]

更多示例可用。

另一种选择是OP将其程序作为库编写,并让用户通过使用OPs库在Haskell中编写程序来输入其函数。Common Lisp通常经过编译,并具有
eval
函数,因此这不是真正的参数。;)@kqr:一般来说,根本没有这种联系。Python和Java都为VM生成字节码,但Python有
eval
,而Java没有(Clojure也生成JVM字节码)。OpenCL是C99,所以它是编译的,对吗?但我可以在运行时构造并运行OpenCL内核,它本质上是
eval
。等等。@kqr这是真的。我的意思是解释语言通常免费获得
eval
实现。已编译的文件必须以某种方式包含解释器或编译器。这就是提示——GHCAPI的包装器。@PetrPudlák谢谢你的回答,它非常适合我的程序。我现在可以让用户输入公式,得到真值表。然而,我发现可执行程序不是一个自包含的可执行程序,它需要ghc和提示来执行…@code4j:想想看。haskell程序如何知道如何在没有与GHC完整版本等效的东西的情况下运行任意字符串?