zio-prelude
zio-prelude copied to clipboard
Consider deriving `IdentityBoth` from `Covariant` and `IdentityFlatten`
Currently, when a function requires IdentityBoth
on some F[+_]
but only Covariant
as well as IdentityFlatten
are in scope, the compilation fails with an implicit not found
.
Should zio-prelude provide automatic derivation for IdentityBoth
given Covariant
as well as IdentityFlatten
?
The process could be as follows:
- move every
IdentityBoth
instance of every data type already providing one to the companion object ofAssociativeBoth
- create a new trait containing something like
sealed trait LowerOrderImplicit {
implicit def derive[F[+_]](implicit
C: Covariant[F],
IF: IdentityFlatten[F]
): IdentityBoth[F] =
new IdentityBoth[F] {
def any = IF.any
override def both[A, B](fa: => F[A], fb: => F[B]): F[(A, B)] =
IF.flatten(C.map((a: A) => C.map((b: B) => (a, b))(fb))(fa))
}
}
- make the companion object inherit from that trait.
I tried to do it, but I failed pretty early, because after moving NonEmptyListInstanceBoth
, I got
[error] /home/felher/sources/ref/zio-prelude/src/test/scala/zio/prelude/NonEmptyListSpec.scala:46:63: could not find implicit value for evidence parameter of type zio.prelude.coherent.AssociativeBothDeriveEqualInvariant[[+A]zio.prelude.NonEmptyList[A]]
[error] testM("associativeBoth")(checkAllLaws(AssociativeBoth)(GenFs.nonEmptyList, Gen.anyInt)),
and I did not have the time to dig deeper. This happened even before defining the LowerOrderImplicit
trait, FWIW.
It think in theory this approach should work for data types in prelude. But after @sideeffffect noted that this might lead to ambiguous implicits, I'm not completely sure what to do if users want to define instances for their own datatype. Since they cant define their specialized instances on the companion object, they might either have to stick with the derived one, or would have to do manual imports. Otherwise they will see ambiguous implicit.