是否有适合集合成员的光学器件?

Is there an appropriate optic for set membership?

我在深度嵌套的异构数据结构中使用 Data.Set,我认为为集合成员创建一个 Prism 会很有帮助。因此:

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

但是,在 review l 插入一个已经存在于 b 中的成员的情况下,这不符合第一棱镜法则 preview l (review l b) ≡ Just b,即,如果 [=16] =]是a的membership lens,b{a},那么review l b也是{a}preview l (review l b)就是null设置,而不是像第一个棱柱定律所要求的那样只是 {a}

有没有更好的方法来捕捉集合成员?我喜欢能够检查成员资格并同时有条件地将集合分解为匹配和不匹配的部分。此外,有一个 optical 来做这件事很有吸引力,因为它捕获了我在代码的其他部分使用 Sets 的所有用例,它使我能够删除我的 import Data.Set 语句来自我包裹的其余部分,这通常向我表明成功的抽象。

Contains类型class成员:

contains :: Contains m => Index m -> Lens' m Bool

当专用于 Set 时是

contains :: Ord a => a -> Lens' (Set a) Bool

想想为什么它是一个 透镜 (而不是棱镜,就像你尝试的那样)可能是一个很好的练习。