在Haskell中编写编译器时,我在处理嵌套数据类型时偶尔遇到了一些特定问题。我将有一个ADT定义类似使用其他数据在Haskell中注释嵌套ADT
data AST = AST [GlobalDecl]
data GlobalDecl = Func Type Identifier [Stmt] | ...
data Stmt = Assign Identifier Exp | ...
data Exp = Var Identifier | ...
在执行上AST一些转变,我可能想简单地随身携带与在表达式中使用带变量的一些额外的数据。到目前为止,我所考虑过的所有这些选项似乎相当尴尬。我可以做一个新的数据类型:
data Exp' = Var' Identifier ExtraInfo | ...
但这意味着我需要一个新的定义Stmt'
,GDecl'
,以形成略有改变AST'
。另一种选择是另一个数据构建器添加到原来Exp
,但只用它在程序中的一个特定部分:
data Exp = Var Identifier | Var' Identifier ExtraInfo | ...
如果你这样做,typechecker再也不能阻止你在错误地使用Var'
该计划的其他部分。 第三个选择是简单地保持周围所有的时间额外的信息,即使它没有相关的程序的其余部分:
data Exp = Var Identifier ExtraInfo | ...
可行的,但它的丑陋,尤其是如果你只需要额外的信息简要。现在,我刚把Map Indentifier ExtraInfo
中的额外信息加上AST
,明确地或通过状态monad。例如,如果您需要使用不同的信息注释同一个Identifier
的不同发生,这可能会变得很尴尬。
有没有人有任何注释嵌套数据类型的优雅技术?
也许尝试'数据Exp a = Var标识符a | ...'?然后可以传递注释但实际上不使用它们的函数在'a'中是多态的,那些不能处理注释的函数将使用Exp()来注释你具有类型为Exp()的函数, - > Exp ExtraInfo',并且需要额外信息的转换将使用'Exp ExtraInfo'。它基本上是“始终保持它”的选项,但类型检查程序能够强制执行使用它的阶段。 – Ben 2014-10-06 01:09:46