2017-09-21 3 views
1

私は最近、ADTリファクタリングしようとしていた - コンストラクタの数がcombinatorically成長してきた - 後方互換セット表現に:このためにはViewPatternsと一致する前にPatternSynonyms argsでマップしますか?

data Tag = TagFoo | TagBar !Text | TagBaz !Int ... -- many more 
      deriving (Eq, Generic, Ord, Show) 

newtype Label = Label (HashSet Tag) 
       deriving (Eq, Generic, Show) 

を、私はの効果にいくつかのパターンの同義語を定義し:

pattern Tags :: [Tag] -> Label 
pattern Tags ts <- ((\(Label ts') -> sort $ HashSet.toList ts') -> ts) 

残念ながら、この:Tagsパターンで

{-# LANGUAGE PatternSynonyms #-} 
{-# LANGUAGE ViewPatterns #-} 

pattern Foo :: Label 
pattern Foo <- Tags [TagFoo] where 
    Foo = Label $ HashSet.singleton TagFoo 

-- (let's say a lone TagBar is invalid) 

pattern FooWithBar :: Text -> Label 
pattern FooWithBar b <- Tags [TagFoo, TagBar b] where 
    FooWithBar b = Label $ HashSet.fromList [TagFoo, TagBar b] 

は、次のように定義しますフォームはエラーが発生しやすくなります。これは、ユーザがOrdの正しいリストに[Tag]リストを提供する必要があるためです。そうでない場合、Tags [TagBar "x", TagFoo]のようなパターンはLabel $ HashSet.fromList [TagBar "x", TagFoo]と一致しません。 (ただし、sortを実行することはさらに悪くなりますが、タグの順序は任意です)。

理想的には、Haskell(または順序付けられていないコンテナ?)は、HashSetの要素をパターンマッチングする方法を提供します。しかし、別の方法は、HashSet.fromListを通じてTags tsパターンのts引数をマッピングして、結果セットを比較することができます

pattern Tags ts <- ((\(Label ts') -> ts' == HashSet.fromList ts) -> True) 

パターン同義語の引数は、ビューパターン関数で使用することはできませんので、これは、しかし、不可能です。しかし、ビュー関数の外で変換をやろうとしている:->の後の部分がパターンで、機能のアプリケーションを許可しないので、

pattern Tags ts <- ((\(Label ts') -> ts') -> HashSet.fromList ts == ts') 

ことも不可能です。

このような種類の一致を可能にするパターンシノニムを定義する他の方法はありますか?

+0

'順不同-containers'はどちらか、このような同義語を定義することはできませんが! – dfeuer

答えて

1

Tagsは本当にパターンである必要がありますか?単に機能を提供すると何が問題になっています:

toLabel :: [Tags] -> Label 

と、ユーザーはガードを使用してい:

someFunction lab | lab == toLabel [TagFoo, TagBar "bar"] = ... 
関連する問題