haskell - 将 Iso 提升到 Bifunctor 的第一个参数

标签 haskell haskell-lens isomorphism bifunctor

Control.Lens.Iso 包含许多很棒的函数,用于将 Iso 提升为有用抽象的各种类型参数。例如:

  • 映射 任意Functor
  • contramapping Contravariant 仿函数
  • dimappinglmappingrmapping 用于 Profunctor
  • 双向映射 Bifunctor

我正在寻找将 Iso 提升到 Bifunctorfirst 参数中的函数,但它似乎不是那里。我目前是这样定义它的:

firsting
  :: Bifunctor f
  => AnIso s t a b
  -> Iso (f s x) (f t y) (f a x) (f b y)
firsting p = bimapping p (iso id id)

这个函数是否已经存在于某处,或者 bimapping p (iso id id) 是否已经尽善尽美?

最佳答案

更新

感谢您的问题,下一个版本的 Control.Lens.Iso will include firstingseconding


iso id id 看起来有点难看。让我们试着把它拆开。

type Iso s t a b =
  forall f p . (Functor f, Profunctor p) =>
                               p a (f b) -> p s (f t)

--plain :: Iso s t s t
--plain = iso id id

plain :: (Functor f, Profunctor p) => p s (f t) -> p s (f t)
plain = id

因此您可以将实现缩减为

firsting p = bimapping p id

这可能是最简洁的形式。如果您想真正深入了解它,请继续阅读。

内联双映射的定义

bimapping :: (Bifunctor f, Bifunctor g) => AnIso s t a b -> AnIso s' t' a' b' -> Iso (f s s') (g t t') (f a a') (g b b')
bimapping f g = withIso f $ \ sa bt -> withIso g $ \s'a' b't' ->
  iso (bimap sa s'a') (bimap bt b't')

然后使用 first 进行简化,您会得到

firsting p = withIso p $ \ sa bt ->
             iso (first sa) (first bt)

我认为这是一个特别明确的表达。它使用 withIsop 分解为构成同构的两个函数,使用 first 提升每个函数以应用于第一个参数双仿函数,然后用 iso 将它们打包备份。如果相关的双仿函数有一个优化的 first 比使用 bimap 做的更好,那么这也将比使用 bimapping 的实现更快>.

内联 iso 给出

firsting p = withIso p $ \ sa bt ->
             dimap (first sa) (fmap (first bt))

最后,内联 withIso(深入研究 Control.Lens.Internal.Iso,我们可能不应该这样做),

firsting p =
  case p (Exchange id Identity) of
    Exchange sa bt ->
      dimap (first sa) (fmap (first (runIdentity #. bt)))

顺便说一下,没有冗余上下文的plain的类型签名是

plain :: p s (f t) -> p s (f t)

这完全一样

plain :: Equality s t s t

关于haskell - 将 Iso 提升到 Bifunctor 的第一个参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34154211/

相关文章:

algorithm - 计算子图实例

c - haskell中的递归数据类型

xml - haskell xml使用HXT库更新文本

algorithm - graph - 如何使用 Tree Isomorphic 解决语言模式匹配问题?

haskell - 如何使用镜头列表?

haskell - 表示短位串的最佳方式是什么?

algorithm - 匹配非同构图

javascript - 是否可以从 JavaScript 调用 hamlet?

haskell - 在haskell中将管道组合成一个循环或循环

haskell - 如何使用 Control.Lens 中的 IndexedTraversal 为每个元素执行索引感知操作?