3

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

  • mapping对于任意Functors
  • contramapping对于Contravariant函子
  • dimapping,对于s lmapping_rmappingProfunctor
  • bimappingBifunctors

我正在寻找将 a 提升Iso到 a 的first参数的函数Bifunctor,但它似乎不存在。我目前正在这样定义它:

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)了?

4

1 回答 1

3

更新

感谢您的提问,下一个版本Control.Lens.Iso 将包括 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

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)

我认为这是一个特别明确的表达。它用于withIso分解p构成同构的两个函数,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
于 2015-12-08T17:15:03.410 回答