私は最近、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')
ことも不可能です。
このような種類の一致を可能にするパターンシノニムを定義する他の方法はありますか?
'順不同-containers'はどちらか、このような同義語を定義することはできませんが! – dfeuer