【发布时间】:2018-01-12 06:49:00
【问题描述】:
我正在考虑解压缩操作,并意识到表达它们的一种方法是遍历 Biapplicative 函子。
import Data.Biapplicative
class Traversable2 t where
traverse2 :: Biapplicative p
=> (a -> p b c) -> t a -> p (t b) (t c)
-- Note: sequence2 :: [(a,b)] -> ([a], [b])
sequence2 :: (Traversable2 t, Biapplicative p)
=> t (p b c) -> p (t b) (t c)
sequence2 = traverse2 id
instance Traversable2 [] where
traverse2 _ [] = bipure [] []
traverse2 f (x : xs) = bimap (:) (:) (f x) <<*>> traverse2 f xs
在我看来,Traversable 的每个实例都可以机械地转换为 Traversable2 的实例。但是我还没有找到一种使用traverse 来实际实现traverse2 的方法,除了在列表之间进行转换,或者使用unsafeCoerce 进行非常肮脏的把戏。有什么好办法吗?
进一步证明Traversable 是Traversable2:
class (Functor t, Foldable t) => Traversable2 t where
traverse2 :: Biapplicative p
=> (a -> p b c) -> t a -> p (t b) (t c)
default traverse2 ::
(Biapplicative p, Generic1 t, GTraversable2 (Rep1 t))
=> (a -> p b c) -> t a -> p (t b) (t c)
traverse2 f xs = bimap to1 to1 $ gtraverse2 f (from1 xs)
class GTraversable2 r where
gtraverse2 :: Biapplicative p
=> (a -> p b c) -> r a -> p (r b) (r c)
instance GTraversable2 V1 where
gtraverse2 _ x = bipure (case x of) (case x of)
instance GTraversable2 U1 where
gtraverse2 _ _ = bipure U1 U1
instance GTraversable2 t => GTraversable2 (M1 i c t) where
gtraverse2 f (M1 t) = bimap M1 M1 $ gtraverse2 f t
instance (GTraversable2 t, GTraversable2 u) => GTraversable2 (t :*: u) where
gtraverse2 f (t :*: u) = bimap (:*:) (:*:) (gtraverse2 f t) <<*>> gtraverse2 f u
instance (GTraversable2 t, GTraversable2 u) => GTraversable2 (t :+: u) where
gtraverse2 f (L1 t) = bimap L1 L1 (gtraverse2 f t)
gtraverse2 f (R1 t) = bimap R1 R1 (gtraverse2 f t)
instance GTraversable2 (K1 i c) where
gtraverse2 f (K1 x) = bipure (K1 x) (K1 x)
instance (Traversable2 f, GTraversable2 g) => GTraversable2 (f :.: g) where
gtraverse2 f (Comp1 x) = bimap Comp1 Comp1 $ traverse2 (gtraverse2 f) x
instance Traversable2 t => GTraversable2 (Rec1 t) where
gtraverse2 f (Rec1 xs) = bimap Rec1 Rec1 $ traverse2 f xs
instance GTraversable2 Par1 where
gtraverse2 f (Par1 p) = bimap Par1 Par1 (f p)
【问题讨论】:
-
如果您还没有,请查看 Conor McBride 的“我左边的小丑,右边的小丑:剖析数据结构”。 (cis.upenn.edu/~cis39903/static/clowns.pdf)
-
@Davislor,我认为这与一种完全不同的“解压缩”有关。
-
@Davislor,使用
Traversable2实现Traversable应该很容易。走另一条路似乎更难。 -
请注意
traverse (f :: a -> f b) ([] :: [a]) = pure ([] :: [b])。这对我来说似乎是一个很好的证据,traverse不足以实现traverse2,因为因此我们需要一个Applicative实例,其中pure ([] :: [b])称为bipure ([] :: [b]) ([] :: [c])(arg. 2 (!)) (不知道关于列表的任何特别之处,因为traverse的实现应该是提供所有列表特定知识的部分)。 IOW,每次调用pure(和(<*>))都会得到一个单态的东西,而不是一个多态的东西,这会妨碍善意。
标签: haskell traversal bifunctor