在Haskell中标记多态树时,如何减少语法混乱?

时间:2015-08-24 16:47:42

标签: haskell pattern-matching

所以我想要一个表示包含一组节点类型的树的类型。我也想要表示在重叠集上定义的类似树的类型。这是Typed AST问题的另一个版本。假设我的节点类型池是:

data Lit = Lit Int
data Var = Var String
data Hole = Hole Int

解析树可以包含LitVar s但不包含Hole s。第二种称为模板的树可以包含Lit s,VarHole s。

为了简单起见,有一种称为Add的递归节点。

data Parse = A Lit | B Var
data Template = C Lit | D Var | E Hole
data Tree a = Leaf a 
            | Add (Tree a) (Tree a)

所以现在我可以声明数据,我仍然可以对其进行模式匹配,唯一的问题是语法杂乱。

aParse = Add (A Lit 3) (B Var "x")
aTemplate = Add (C Lit 4) (E Hole 3)
fun (Add (A lit) (B var) = ...

我想要的是一些与之相似的糖:

ParseLit = A . Lit
TempLit = C . Lit 

显然,构造函数(非类型)的组合的别名在Haskell中是不合法的。但是写这个最干净的方法是什么,避免尽可能多的锅炉?

1 个答案:

答案 0 :(得分:14)

PatternSynonyms语言扩展程序可以在此处提供帮助。它允许您为模式指定别名:

#include<cmath>
#include<sstream>

int main() {
    std::ostringstream o;
    o << M_PI;
    std::string s = o.str();
    char * p = s.c_str(); // pointer to chars
}

有两种模式同义词:双向(如示例中所示)和单向。双向的也可以用作构造函数:

{-# LANGUAGE PatternSynonyms #-}

pattern ParseLit x = A (Lit x)

someFunc :: Parse -> Int
someFunc p = case p of
    ParseLit x -> x
    _ -> 0