adjunctions
adjunctions copied to clipboard
New Representable methods feel cramped
We now have
collect1 :: Functor1 w => (forall x. g x -> f x) -> w g -> f (w Identity)
We can generalize this immediately:
coll2 :: (Applicative h, Functor1 w) => (forall x. g x -> f x) -> w g -> f (w h)
coll2 f = cotraverse1 (map1 (pure . runIdentity)) . map1 f
I don't know if it's possible to weaken the Applicative
constraint.
Ah, like this:
coll1
:: Functor1 w
=> (forall x. x -> h x) -> (forall x. g x -> f x) -> w g -> f (w h)
This can avoid an extra fmap (map1 (p . runIdentity))
at the end, compared to the current collect1
.
No no no, that's not the way to do it either. Here we go:
collection
:: Functor1 w
=> (forall x. g x -> f (h x))
-> w g -> f (w h)
collection f =
tabulate
. (\w i -> map1 (flip index i . getCompose) w)
. map1 (Compose #. f)
Isn't that more satisfying?
cotraverse1
then becomes
cotraverse1' :: Functor1 w => (w h -> a) -> w (Compose f h) -> f a
which is unsatisfying in just the right way. Finally, we get to the most powerful method,
cotraverseMap1' ::
Functor1 w => (w h -> a) -> (forall x. g x -> f (h x)) -> w g -> f a
cotraverseMap1' f g = cotraverse1' f . map1 (Compose . g)
Lovely, eh?
Isn't that more satisfying?
The point of the new methods is to avoid index
since it's O(n) for instances like Stream
.
cotraverse1 then becomes
@sjoerdvisscher also suggested that version on twitter. As I replied there, I had that version at one point but found that the Identity version is more convenient. The compose version should also be added though, and could replace a bit of code duplication in the Cofree
and (:.:)
instances. I can make a PR for this and a couple other additions I've had in mind.
I don't think the compose version needs to be a method though; it can just be a derived function.
No comment on that particular practicality, but I've run into another rather annoying one: the cotraverse1
and distribute1
methods are incompatible with GeneralizedNewtypeDeriving
. Ouch! This isn't really surprising, since distribute
is as well. But that makes me very tempted to say we should omit those and just have collect1
and cotraverseMap1
.