Closed kubukoz closed 6 years ago
Initial discussion about the old EqK
and drawbacks:
https://gitter.im/typelevel/cats?at=5b33fa45479ca26689854ba6
Looks like the reason to remove EqK
originally was to loosen the requirements for tests - in places where an EqK[F]
and an Eq[A]
was required, the removal made it just a requirement on Eq[F[A]]
.
I believe we could leave these tests unchanged and still have EqK
in the library.
This affects instances for any fixpoint data type like Cofree
.
An alternative solution is what matryoshka did: simulating lazy implicits using Delay[Eq, F]
-
Also, maybe we don't need to support binary type constructors as well - the usecase in which I'm hitting this wall is S[_]
, so it can't be a type of an arbitrary kind. If S[_]
were Either[Int, ?]
or Either[?, Int]
, we should be able to define an EqK
for both of these variants.
I'm relatively certain Defer
solves this problem.
Edit: No it doesn't. I was confused. Delay
from Matryoshka does solve it, but Defer
as referenced in #2279 does not.
I prepared a POC for solving it with Delay (which has its own problems), for anyone interested in the issue: https://github.com/typelevel/cats/pull/2316
I don't like the idea that having Eq
for Cofree
would require another dependency, let alone shapeless (if we were to implement instances for cats simpilar to what you did in that PR for scalaz)... but if there's a decision that we don't want to add Delay
in some shape of form, that might be the best option indeed
https://gist.github.com/xuwei-k/118230f49c6522bddfcf1ef137c11945 byname implicit (since Scala 2.13)
You definitely don't want to be using Lazy
at this point ...
guess we'll just have to wait for 2.13 ;)
Closing, I suggest to wait with the original issue until 2.13 is available, then we can use lazy implicits to add an instance to cats. I'll post more in the issue.
...or at least some of them.
Reasoning: in #2300, I was trying to implement
Eq[Cofree[S, A]]
using implicit instances ofEq[S[Cofree[S, A]]]
andEq[A]
. That would look like this:However, any attempt at e.g.
Eq[Cofree[List, Int]]
will fail compilation due to an diverging implicit expansion - and it makes sense, sinceEq[List[Cofree[List, A]]]
needs anEq[Cofree[List, A]]
, which is exactly what we're trying to construct.The same situation will happen if someone tries to implement
Order
orShow
.Since we don't have a mechanism for shapeless-style lazy implicits, it doesn't seem possible to implement such instances without changes outside of
Cofree
.One solution to this problem that I see is creating a higher kinded variant of
Eq
, similar toSemigroup
/SemigroupK
:I believe that's
Eq1
in Haskell: http://hackage.haskell.org/package/base-4.11.1.0/docs/Data-Functor-Classes.html#g:2Having that, we might remove the current instances of
Eq
for higher kinded types likeOption
:and replace them with instances of
EqK
:To make it possible to seamlessly get an
Eq[Option[A]]
for anA : Eq
, we could add a derivation method:or, alternatively (and this would probably make it possible to keep binary compatibility), add instances of
EqK
alongside the old instances, and make the old instances use the implementations fromEqK
instances underneath (the old instances could be removed later, at a point when we can break compatibility).The same thing could happen to
Order
andShow
.Another idea would be to introduce lazy implicits to Cats.