Niejawna rozdzielczość typów lambda wydaje się zepsuta. Najwyraźniej kompilator najpierw odrzuca typ, a następnie niedopasowuje liczbę parametrów typu.
to 'uproszczony' Przykład:
Definiowanie monady i dwie cechy. One
jest podobna do Either
. Two
jest podobna do EitherT
trait Monad[F[_]]
trait One[A, B]
object One {
implicit def m[A]: Monad[({ type T[x] = One[A, x] })#T] = ???
}
trait Two[F[_], A]
object Two {
implicit def m[F[_]]: Monad[({ type T[x] = Two[F, x] })#T] = ???
}
Definiowanie aliasu typu oraz klasę przypadku częściowego zastosowania One
z String
jak to pierwszy parametr. Wersja tego rozwiązania może być używana jako obejście tego problemu.
type OneX[A] = One[String, A]
case class OneY[A](value: OneX[A])
object OneY {
implicit def m(implicit ev: Monad[OneX]): Monad[OneY] = ???
}
Niejawne rozwiązanie wszystkich "prostych" typów działa.
implicitly[Monad[OneX]]
implicitly[Monad[({ type T[x] = One[String, x] })#T]]
implicitly[Monad[OneY]]
Definiowanie kilka aliasów typu, które częściowo odnoszą Two
type TwoX[A] = Two[OneX, A]
type TwoY[A] = Two[({ type T[x] = One[String, x] })#T, A]
type TwoZ[A] = Two[OneY, A]
Tutaj widzimy, że ktoś przy użyciu typu lambda zawiedzie.
implicitly[Monad[TwoX]]
implicitly[Monad[TwoY]] // fails
implicitly[Monad[TwoZ]]
Tutaj widzimy, że wszystkie typy lambda, które używają aliasu typu fail. Tylko ten, który rzeczywiście odnosi się do typu stabilnego z pojedynczym parametrem, kończy się sukcesem.
implicitly[Monad[({ type T[x] = Two[OneX, x] })#T]] // fails
implicitly[Monad[({ type T[x] = Two[OneY, x] })#T]]
implicitly[Monad[({ type T[x] = Two[({ type T[x] = One[String, x] })#T, x] })#T]] //fails
Moja wiedza na temat kompilatora jest dość ograniczona i może być związana z błędem @ Punkty TravisBrown do.
Wygląda na to, że widzisz [tego błędu] (https://issues.scala-lang.org/browse/SI-6895) (chociaż mógłbym przysiąc, że napisałem dokładnie ten kod wcześniej). –