Data.Distributive 是 Data.Traversable 的对偶。它提供了 distribute 函数,可以专门化,例如如f (Stream a) -> Stream (f a) 或distribute :: f (Vec n a) -> Vec n (f a)。后一个示例是您的函数族的同质变体。
但是我们可以概括Data.Distributive 有点像镜头概括函子一样。输入Colens:
type Colens s t a b = forall f. Functor f => (f a -> b) -> f s -> t
这是Control.Lens.Each的镜子:
class Coeach s t a b | s -> a, t -> b, s b -> t, t a -> s where
coeach :: Colens s t a b
instance (a~a', b~b') => Coeach (a,a') (b,b') a b where
coeach f p = (f $ fst <$> p, f $ snd <$> p)
instance (a~a2, a~a3, b~b2, b~b3) => Coeach (a,a2,a3) (b,b2,b3) a b where
coeach f p = ...
...
就像each 一样,我们可以遍历元组
each_id1 :: Applicative f => (f a, f a) -> f (a, a)
each_id1 = each id
each_id2 :: Applicative f => (f a, f a, f a) -> f (a, a, a)
each_id2 = each id
使用coeach,我们可以遍历元组:
coeach_id1 :: Functor f => f (a, a) -> (f a, f a)
coeach_id1 = coeach id
coeach_id2 :: Functor f => f (a, a, a) -> (f a, f a, f a)
coeach_id2 = coeach id
不过,这仍然是同质的。我对lens了解不多,所以不能说是否存在异类each和对应的coeach。