现在,我有一个 AST 表达式,它在递归类型上是多态的:
data Expr a = Const Int
| Add a a
Run Code Online (Sandbox Code Playgroud)
这非常有用,它允许我使用一种类型进行普通递归 ( Fix Expr),而在需要附加额外信息时使用另一种类型( Cofree Expr ann)。
当我想在这个递归方案中引入另一种类型时会出现问题:
data Stmt a = Compound [a]
| Print (Expr ?)
Run Code Online (Sandbox Code Playgroud)
如果Expr不引入额外的类型变量并破坏与我已经编写的所有通用函数的兼容性,我不确定该术语的内容。
可以这样做吗,如果可以,这是一种有用的模式吗?
我有一个AST,我正在使用它进行注释Cofree:
data ExprF a
= Const Int
| Add a
a
| Mul a
a
deriving (Show, Eq, Functor)
Run Code Online (Sandbox Code Playgroud)
我type Expr = Fix ExprF用来表示未标记的AST,并type AnnExpr a = Cofree ExprF a代表标记的AST .我已经找到了一个函数,通过丢弃所有注释将标记的AST转换为未标记的AST:
forget :: Functor f => Cofree f a -> Fix f
forget = Fix . fmap uncofree . unwrap
Run Code Online (Sandbox Code Playgroud)
这看起来可能是某种类似的catamorphism(我正在使用Kmett的recursion-schemes包中的定义).
cata :: (Base t a -> a) -> t -> a
cata f = c where c = f . fmap …Run Code Online (Sandbox Code Playgroud) haskell functional-programming category-theory catamorphism recursion-schemes