将 Iso 提升到 Bifunctor 的第一个参数
Lifting an Iso into the first argument of a Bifunctor
Control.Lens.Iso
包含许多奇妙的函数,用于将 Iso
s 提升为有用抽象的各种类型参数。例如:
mapping
任意 Functor
s
contramapping
对于 Contravariant
函子
dimapping
、lmapping
和 rmapping
Profunctor
s
bimapping
对于 Bifunctor
s
我正在寻找将 Iso
提升到 Bifunctor
的 first
参数中的函数,但它似乎不存在。我目前是这样定义的:
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 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
Control.Lens.Iso
包含许多奇妙的函数,用于将 Iso
s 提升为有用抽象的各种类型参数。例如:
mapping
任意Functor
scontramapping
对于Contravariant
函子dimapping
、lmapping
和rmapping
Profunctor
sbimapping
对于Bifunctor
s
我正在寻找将 Iso
提升到 Bifunctor
的 first
参数中的函数,但它似乎不存在。我目前是这样定义的:
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 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