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
これについて私が気に入っているのは、派生句を追加する以外はデータ型を変更する必要がなく、読み取り可能であることです。もちろん、欠点は、これらが動的チェックであることです。私の場合、アサートのようなチェックでプログラミング エラーを検出するだけなので、これで問題ありません。