Closed sjoerdvisscher closed 7 years ago
To be more precise. p Void a
is equivalant to p Void Void
but p a a
is not, so I suspect we don't actually want p a a
.
I actually need p a a
to deal with constants that don't need to be touched. It's just a coincidence that zero
can be implemented. I really just need it as "identity" but Identity
and id
are already used so often, and end
isn't and still technically a correct term.
Oh, I now realise that the implementation can just be zero = end
and probably is not worth including. In my code I had zero :: p (V1 a) (V1 b)
.
Hmm, so perhaps you actually want Strong
?
I'm very suspicious of p a a
and I suspect that it's a coincidence that it works and you actually want something else.
Actually I'm not suspicious of it. It's a perfectly good class but it is strictly less general (in combination with ProductProfunctor
) than Strong
.
Is Strong
sufficient for your needs?
This is the only place where I use it: https://github.com/sjoerdvisscher/one-liner/blob/master/src/Generics/OneLiner/Internal.hs#L110
So what I need is p (K1 i c a) (K1 i c b)
. K1
is from GHC.Generics
and defined as
newtype K1 (i :: *) c (p :: *) = K1 { unK1 :: c }
so after dimap unK1 K1
I just need a p c c
. I don't see how Strong
would help me here.
At the very least you can get p c c
from p () ()
and first' :: p a b -> p (a, c) (b, c)
.
I wonder if ProductProfunctor p, Strong p
is actually equivalent to ProductProfunctor p, ProfunctorEnd p
.
Ah, indeed! It looks like they are.
first' p = p ***! end
second' p = end **! p
And as you said you can get end
from empty
and first'
. Scratch that class then.
The only ProfunctorEnd
instance that isn't Strong
is Joker
. With the above the instance would become
instance Alternative f => Strong (Joker f) where
first' (Joker fb) = Joker $ liftA2 (,) fb Alternative.empty
But I could work around this missing instance. Using Alternative
just for its empty
was ugly anyway.
The Product/SumProfunctor instances are uncontroversial so I merged them anyway.
Having thought about it some more I believe that ProfunctorEnd
is a meaningful class so let me know if you want me to add that too.
With ProductProfunctor being Profunctor+Applicative and ProfunctorEnd being Strong+Applicative there only has to be a nice replacement for SumProfunctor and I would not need this whole package...
SumProfunctor p
is the same as Decidable (Flip p) a
.
But there's actually good reason to use this package after all! There can be different instances of Applicative (p a)
, depending on if you're seeing p
as a Profunctor
or as a Bifunctor
. For example the instance for Clown f a
would need Divisible f
or Alternative f
respectively.
Thanks!
Can you explain the meaning of
end
? If it's supposed to be the identity of+++!
shouldn't it beend :: p Void a
?