Control.Lens.Iso包含许多出色的函数,用于将Iso提升为各种类型的有用抽象参数。例如:
mapping的Functorcontramapping的Contravariant函子dimapping,lmapping和rmapping的Profunctorsbimapping for Bifunctors我正在寻找将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)就像它得到的一样好?
发布于 2015-12-08 17:15:03
更新
感谢您的提问,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 thttps://stackoverflow.com/questions/34154211
复制相似问题