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