【问题标题】:How should I represent an AST annotated with additional information?我应该如何表示带有附加信息注释的 AST?
【发布时间】:2013-04-24 23:53:17
【问题描述】:

假设我有一个用某种语言表示 AST 的简单数据类型:

data Term = Var String
          | Num Integer
          | Expr [Term]

(实际上它显然会有比这更多的构造函数。)

我可以使用它来编写一个与 AST 结构匹配的简单评估函数:

eval :: Term -> Result
eval (Var name)   = lookup name
eval (Num n)      = return n
eval (Expr exprs) = ...

我能否在不改变模式匹配工作方式的情况下使用行号等信息来注释 AST?

(如果我不介意更改模式,当然可以使用记录语法或视图模式。)

【问题讨论】:

  • data AtLine a = AtLine Int a这样的容器ADT怎么样?
  • @NikitaVolkov:这正是我会用 ViewPatterns 之类的东西做的事情。我只是想知道是否有一种很好的方法可以完全避免更改模式匹配。
  • 如果你匹配的是Term类型,为什么会影响模式匹配?
  • @NikitaVolkov:因为我想在使用术语时保留元数据。例如。 eval 可能会引发错误,所以我必须知道它来自哪一行代码。
  • 你可以在evalAtLine :: AtLine Term -> Result这样的外部函数中截获这个错误,并用行信息重新抛出它。

标签: haskell


【解决方案1】:

为什么不多态地表示 AST

data Term term = Var String
      | Num Integer
      | Expr [term]

那么你原来的Term 类型是

newtype SimplTerm = SimplTerm (Term (SimplTerm))

您可以使用视图模式轻松地做您想做的事情

data AtLine = AtLine (Term AtLine) Integer

view :: AtLine -> Term AtLine
view (AtLine x _) = x

eval (view -> Var name) = lookup name
eval (view -> Num n) = numResult n
eval (view -> Expr expr) = listResult (map eval expr)

或使视图多态

class AST t where
   term :: t -> Term t
instance AST SimplTemr where
   term (SimplTemr x) = x
instance AST AtLine where
   term (AtLine x _) = x

eval :: AST t => t -> Result
eval (view -> Var name) = lookup name
eval (view -> Num n) = numResult n
eval (view -> Expr expr) = listResult (map eval expr)

对于错误处理,我希望有一种方法可以让视图模式出现在 monad 中,但这就是生活(如果 view 函数在 cps 中完成,你可以这样做,因此将延续作为参数而不是而不是返回一个值)。

【讨论】:

  • recursion-schemes (on hackage) 有一个Fix 类型和Foldable 类型类,分别与SimpleTemrAST 非常相似。
猜你喜欢
  • 1970-01-01
  • 2012-02-02
  • 1970-01-01
  • 2018-10-03
  • 2015-06-17
  • 2012-09-20
  • 2018-03-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多