Haskell 我应该如何表示带有附加信息注释的AST?

Haskell 我应该如何表示带有附加信息注释的AST?,haskell,Haskell,假设我有一个用某种语言表示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 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吗


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

为什么不以多态方式表示AST

data Term term = Var String
      | Num Integer
      | Expr [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中,但这就是life(如果
view
函数是在cps中完成的,因此可以将continuation作为参数,而不是返回值)

那么像
data AtLine a=AtLine Int a
这样的容器ADT呢?@NikitaVolkov:这正是我对ViewPatterns这样的东西所做的。我只是想知道是否有一种很好的方法可以避免更改模式匹配。如果匹配的是
术语
类型,为什么会影响模式匹配?@NikitaVolkov:因为我想在使用术语时保留元数据。例如,
eval
可能会引发错误,因此我必须知道它来自哪一行代码。您可以在外部函数中拦截此错误,如
evalAtLine::AtLine Term->Result
,并使用行信息重新显示它。
递归方案
(关于hackage)具有一个
Fix
类型和
Foldable
类型类,分别与
SimpleTemr
AST
非常相似。