【问题标题】:Haskell: how to evaluate a String like "1+2"Haskell:如何评估像“1 + 2”这样的字符串
【发布时间】:2011-04-07 14:42:59
【问题描述】:

实际上,我有一些公式,例如"x + y",即String。 我设法将x/y 变量替换为特定值,例如"1.2",它仍然是String 类型。 现在我有像"1 + 2" 这样的表达。

所以问题是如何对一个字符串类型的表达式求值并得到结果。

ps:我想要像read 这样的东西,它可以直接转换整个字符串表达式,而不是逐个处理运算符(+/-等)。那可能吗?

【问题讨论】:

  • 当然有可能。但我觉得你应该对表达式使用更好的表示。一个线索可能是您的短语“转换整个字符串表达式”。问题是:转换成 what?
  • 我认为 yoz 想要评估它,并使用术语转换作为“转换为结果”。
  • @mdm,当然,这就是我要问的原因:让他意识到转换和评估是不同的事情。他要么直接评估字符串(他已经拒绝了),要么转换(转换成什么?这是关键问题)然后评估它。
  • 你想要eval "1+2" :: Int这样的东西吗?
  • @rampion 是的,我想看到类似的东西。它是否存在于标准的 haskell 中(没有时髦的包...)?

标签: haskell eval


【解决方案1】:

您的问题留有很大的解释空间。我猜你不习惯构建一个包含词法分析、解析、类型检查和评估的完整管道。长答案将涉及您定义要评估的语言(只是带有“+”的整数,也许所有带有“+”、“-”、“*”、“/”或什至更大的语言的有理数?)并执行每个该语言的上述步骤。

简短的回答是:要评估 Haskell 表达式,其中包括您可能正在谈论的基本数学运算符,只需使用“提示”包:

$ cabal install hint
...
$ ghci
> import Language.Haskell.Interpreter
> runInterpreter $ setImports ["Prelude"] >> eval "3 + 5"
Right "8"

耶!

【讨论】:

  • 我试图找到一种无需词法分析、语法定义等即可评估字符串表达式的方法。C# 可以通过在运行时编译代码来实现这一点。所以实际上我只是想知道 Haskell 中是否有类似的东西。你的回答正是我需要的。非常感谢~
  • @yoz 很高兴我能帮上忙。显然,您可以阅读haddock documents yourself,但很快interpret 函数将为您提供多态类型的结果(不是字符串表示),根据您的需要,这可能会更好。快乐的黑客攻击。
  • 任何方法都可以使用标准 Haskell 做到这一点,而无需安装 hint
  • Glasgow Haskell 提供了一个 API,这就是hint 使用的。否则(使用规范中出现的纯 Haskell)你运气不好,必须编写解释器或其他自定义解决方案..
【解决方案2】:

可能值得阅读Real World HaskellParsec 部分。您可以将其解析为表达式树,然后替换其中的值。当您使用 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,它会在映射中应用绑定,然后在可能的情况下计算结果。

【讨论】:

  • 我认为@yoz 期望更多的内置函数eval :: String -> Doubleeval :: String -> Either ErrorMessage Double 可能会更一点 haskellish。但是,正如大多数人指出的那样:表示为字符串的表达式是不好的。最好使用 Jeff 展示的语法树。
【解决方案3】:

好吧,我一直在努力反对hint,但我现在放弃了。 我知道提示可以做到这一点,但我不确定如何。 [编辑] 请参阅 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: `+'"])

+ 运算符不在范围内???呜呜呜……

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 类不在范围内???呃……

我邀请比我知识渊博的人详细解释提示的细节。

【讨论】:

  • 你需要setImports,看我的回答。
猜你喜欢
  • 2016-05-22
  • 2016-07-26
  • 2020-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多