data Foo = Bar1
| Bar2 Foo Foo
| Bar3 Foo
| Bar4 Foo Foo Foo
现在,假设有人建了一Foo
棵树,我想检查 Foo 值的参数是否有效。构造函数参数的规则是:
Bar2 Bar1 Foo
Bar3 (Bar2|Bar3|Bar4)
Bar4 Bar1 Bar1 (Bar1|Bar4)
我知道值的构造函数,只想检查直接参数,没有递归。像这样:
bar2 Bar1 Bar1 = True
bar2 Bar1 (Bar2 {}) = True
bar2 Bar1 (Bar3 _) = True
bar2 Bar1 (Bar4 {}) = True
bar2 _ _ = False
例如,对于 Bar4 类似:
bar4 Bar1 Bar1 Bar1 = True
bar4 Bar1 Bar1 (Bar4 {}) = True
bar4 _ _ _ = False
我怎样才能最简洁地表达这些条件?在某些情况下,列出所有组合有点过多。据我所知,不存在用于模式匹配的“OR”语法。
更新
我改编了丹尼尔的解决方案并得出了这个结论:
data Foo = Bar1
| Bar2 Foo Foo
| Bar3 Foo
| Bar4 Foo Foo Foo
deriving (Data, Typeable)
bar2 a b = a `isOf` [Bar1] && b `isOf` [Bar1,Bar2{},Bar3{},Bar4{}]
bar4 a b c = [a,b] `areOf` [Bar1] && c `isOf` [Bar1,Bar4{}]
isOf l r = toConstr l `elem` map toConstr r
areOf l r = all (`isOf` r) l
我喜欢这个的原因是我不必更改我的数据类型,除了添加派生子句,而且它是可读的。当然,缺点是这些是动态检查。就我而言,这很好,因为它只是用于类似断言的检查以发现编程错误。