I’m using Data.Set
s in deeply-nested heterogeneous data structures, and thought it would be helpful to create a Prism
for set membership. Hence:
membership :: (Ord a) => a -> Prism' (Set a) (Set a)
membership a = prism (Set.insert a) g
where g as = if Set.member a as
then Right $ Set.delete a as
else Left as
However, this fails the first prism law, preview l (review l b) ≡ Just b
, in the case where review l
inserts a member that is already present in b
, viz., if l
is the membership lens for a
, and b
is {a}
, then review l b
is also {a}
, and preview l (review l b)
is just the null set, rather than just {a}
as the first prism law requires.
Is there a better optic for capturing set membership? I like being able to check membership and conditionally decompose the set into the matching and non-matching parts simultaneously. Additionally, having an optic to do this is appealing because, since it captures all the use-cases I have for working with Set
s in other parts of my code, it enables me to remove my import Data.Set
statements from the rest of my package, which often indicates successful abstraction to me.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…