在我解决离散数学的程序中,我想让用户输入一串逻辑运算; 例如,如果用户输入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
答案 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库是开始的地方。