我有这样的数据结构:
data IfTree = If Expr Statement IfTree | Else Statement | EndIf
data Statement = IfStatement IfTree
想要的是不可能做任何这些组合:
IfStatement $ Else ...
IfStatement $ EndIf
IfStatement
应该只能使用If
。
我知道我可以隐藏数据构造函数,只暴露在幕后组成它们的函数,但我想在数据类型中限制它。
更新
我试图做的是笨重的。由于出色的答案和评论,给出了一个更好的处理方法:
data Statement = If Expr Statement (Maybe Statement) | ...
甚至:
data Stat = IfStat Expr Stat | IfElseStat Expr Stat Stat | …
答案 0 :(得分:4)
这将是传统的做法:
data Stat = IfStat Expr Stat (Maybe Stat) | BarStat | BazStat | …
data Expr = FooExpr | …
-- if (foo) bar;
IfStat FooExpr BarStat Nothing
-- if (foo) bar; else baz;
IfStat FooExpr BarStat (Just BazStat)
这个想法是将语言的语法编码为数据类型,或者至少是重要的位。 Else
和EndIf
在If
之外没有意义,因此您实际上并不需要代表它们。
您可以将Maybe
内联到语句数据类型中:
data Stat = IfStat Expr Stat | IfElseStat Expr Stat Stat | …
或者,如果它对您的语言有意义,您可以为空语句添加表示法:
data Stat = IfStat Expr Stat Stat | EmptyStat | …
-- if (foo) bar;
-- if (foo) bar; else;
IfStat FooExpr BarStat EmptyStat
-- if (foo) bar; else baz;
IfStat FooExpr BarStat BazStat
但是,如果您想在以后进行精确的漂亮打印,那么将这样的事情标准化可能会有问题。
可以类似地处理块语句:
data Stat = … | BlockStat [Stat] | …
-- if (foo) { bar; baz; }
IfStat FooExpr (BlockStat [BarStat, BazStat]) EmptyStat
答案 1 :(得分:2)
问题是If
不是只是Else
。你应该定义像
data If = IfNoElse Expr Statement | IfElse Expr Statement Statement
data Statement = If If | While | ...