【问题标题】:Is there an appropriate optic for set membership?是否有适合集合成员资格的光学器件?
【发布时间】:2021-04-11 18:56:15
【问题描述】:

我在深度嵌套的异构数据结构中使用Data.Sets,并认为为集合成员创建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 中的成员,即,如果la 的成员镜头,则这不符合第一棱镜定律preview l (review l b) ≡ Just b ,而b{a},那么review l b 也是{a},而preview l (review l b) 只是空集,而不是第一棱镜定律要求的{a}

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

【问题讨论】:

  • at/alterF 适合你吗?就光学词汇而言,这是对Set 的“最佳”描述。
  • 特别是请求的分解a -> Set a -> (Bool, Set a)就是alterF (, False),也应该是flip at (, False)或者\x -> at x %%~ (, False)
  • 谢谢,我忘记了 Sets 可以被视为类似 Map 的容器,因此可以与 At 一起使用。 (虽然,我不确定当 Set 不是 Traversable,甚至是 Functor 时,如何绕过法律 ix k ≡ at k . traverse。)

标签: haskell set haskell-lens lenses


【解决方案1】:

有一个Contains类型的类有一个成员:

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

当专门用于Set 时是

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

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

【讨论】:

  • 我的理解是contains是一个透镜,而不是棱镜,因为member (a :: a)是所有as :: Set a的有效投影。
猜你喜欢
  • 1970-01-01
  • 2011-01-23
  • 1970-01-01
  • 2020-05-13
  • 2011-04-10
  • 2011-07-11
  • 2016-09-19
  • 2017-01-29
  • 2011-07-10
相关资源
最近更新 更多