实际上我有一些类似"x + y"
的公式,它是String
。
我设法将x/y
变量替换为"1.2"
等特定值,这仍然是String
类型。
现在我的表达式为"1 + 2"
。
所以问题是如何评估字符串类型的表达式并获得结果。
ps:我想要read
,它可以直接转换整个字符串表达式,而不是逐个处理运算符(+/-等)。那可能吗?
答案 0 :(得分:19)
你的问题留下了很大的解释空间。我猜你不习惯建立整个lexing,解析,类型检查和评估的整个流程。很长的答案将涉及你定义你想要评估的语言(只是用'+'整数,也许所有的理性用'+',' - ''*','/',甚至更大的语言?)并执行每个语言该语言的上述步骤。
简短的回答是:评估Haskell表达式,其中包括您可能正在讨论的基本数学运算符,只需使用“提示”包:
$ cabal install hint
...
$ ghci
> import Language.Haskell.Interpreter
> runInterpreter $ setImports ["Prelude"] >> eval "3 + 5"
Right "8"
耶!
答案 1 :(得分:5)
可能值得阅读Parsec的Real World Haskell部分。您可以将其解析为表达式树,然后替换值。当您使用Parsec时,您将使用类型构建表达式树(非常粗略,我确定我犯了一些错误,我将在修复程序中编辑当人们指出他们的时候!)就像下面那样。
data Op = Plus | Minus
data Term = Variable String
| Value Int
data Expression = Expr Expression Op Expression
| Term
然后1 + 2将是(Expr (Variable "x") Plus (Variable "y"))
,您可以应用适当的替换。
为了得到结果,我猜你可以找到一个简单的函数evaluate :: Map String Int -> Expression -> Either ErrorMessage Int
,它可以在地图中应用绑定,然后在可能的情况下计算结果。
答案 2 :(得分:2)
好吧,我一直在反对hint,但我现在放弃了。 我知道提示可以做到这一点,但我不确定如何。 [edit] 请参阅TomMD关于如何为提示设置导入的答案。 [/编辑]
import Language.Haskell.Interpreter (eval, runInterpreter, Interpreter, InterpreterError)
main = do let resIO = eval "3" :: Interpreter String
res <- runInterpreter resIO
print res
这无趣地产生Right "3"
作为结果。我尝试了以下变体,只是遇到了令人困惑的错误:
... eval "3 + 3" ....
-- yields --
Left (WontCompile [GhcError (errMsg = "Not in scope: `+'"])
+
运算符不在范围内??? WTF ...
import Language.Haskell.Interpreter (interpret, as, runInterpreter, Interpreter)
main = do let resIO = interpret "3" (as :: Int) :: Interpreter Int
res <- runInterpreter resIO
print res
-- yields --
Left (WontCompile [GhcError (errMsg = "Not in scope: type constructor or class 'Int'")])
Int
类不在范围内???啊...
我邀请那些比我更有知识的人来阐述提示的细节。