【问题标题】:How can one parse a function of unknown type in Haskell?如何在 Haskell 中解析未知类型的函数?
【发布时间】:2014-06-27 11:18:59
【问题描述】:

我是 Haskell 新手,我正在尝试编写一个解析器来评估一组特定的简单 Haskell 表达式。但是,当我事先不知道它们是什么类型时,我在使用函数时遇到了困难。

例如,假设我知道我要解析的字符串的计算结果是一个整数。以下是字符串可能是什么的几种可能性。

"succ 4"

"head [5,6,7]"

"sum [1,3,1]"

"length [a,b,c,d,e]"

"pred $ sum $ take 3 $ iterate succ 1"

天真地,我想为最后一个示例做的事情就是这样的过程。

  1. 解析出函数pred,推断它的类型为(Enum a) => a -> a,并且我的字符串表示一个整数,而字符串的其余部分(在美元之后)仍然表示一个整数。

  2. 解析出函数 sum 并推断出我现在正在尝试评估整数列表。

  3. 解析出函数take并推断出我正在寻找一个整数和一个整数列表。

  4. 解析出 3 并推断字符串的其余部分应该是整数列表。

  5. 解析出iterate 并推断我正在寻找Int -> Int 类型的函数和一个整数。

  6. 解析出succ1

  7. 执行评估。

问题在于,在流程的每个阶段,我遇到的下一个对象有许多可能的类型,如示例所示。所以我不能编写一些通用解析器来提取一个函数并留下一个表示其参数(或参数)的字符串。但是,如果我必须为每一种可能的函数编写单独的解析器,那么它很快就会变成一场噩梦,尤其是当我必须查看多个变量的函数时。

我意识到它并没有那么糟糕,因为许多函数是为几种不同的类型定义的。但是,例如,如果我说“如果字符串以“succ”开头,然后将其拉出并将 succ 应用于字符串其余部分的评估”,那么它会抱怨我应该指定我正在处理Enum 类中的一个类型。但是当我处理不在该类中的类型时,我遇到了麻烦。

完全披露:我正在使用 Graham Hutton 书中的简单解析器来构建我想要构建的东西。所以也许答案是有更高级的解析器来处理这类问题,我应该改用它。

【问题讨论】:

  • 解析 Haskell 表达式不应该与类型有任何关系(除了像[1, 3 .. 9 :: Int] 中的实际显式注释)。只需将所有内容解析为无类型,然后您可以考虑在生成的 AST 上实现类型统一器。 — 显然,您不仅要解析代码,还要解释代码,但这是另一个问题,而且确实不像在动态语言中那样工作。像 Hugs 这样的 Haskell 解释器仍然通过“编译”经过类型检查的 AST 来工作。

标签: haskell interpreter


【解决方案1】:

正如评论中所指出的,编译器和解释器通常会分多次工作,并且不要试图在每次通过时做太多的工作。

解析通常是一次,可能在词法分析之前。接下来是类型检查,然后是编译器翻译成目标语言(通常是多遍),或者是解释器,评估。对于快速而肮脏的实验或动态语言,您可以省略类型检查。

您应该首先定义一个抽象语法树来表示已解析的表达式 - Haskell 代数数据类型非常适合此。例如,您的 "succ 4" 可能会解析为像 Apply (Symbol "succ") (Int 4) 这样的术语。您只需要本地信息来生成它,而不是周围值的类型 - 例如4 转换为 Int 4 仅仅是因为它是一个数字而不是一个符号。

然后您可以定义一个类型检查器来处理语法树,或者直接跳到评估它并检查类型是否动态有意义。对 Haskell 之类的语言进行正确的类型检查并不简单 - 如果您真的想这样做,经典论文 "Typing Haskell in Haskell" 可能是最好的起点。

【讨论】:

  • 谢谢——这很有帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-26
  • 2014-05-04
  • 2013-04-07
  • 1970-01-01
  • 2013-10-21
相关资源
最近更新 更多