Рассмотрим следующее определение типа:
trait LiftF[F[_], G[_]] {
def liftF[A](fa: F[A]): G[A]
}
При предоставлении требования для неявного этого типа в контексте контекста (используя плагин типа кинопроектора) мы должны написать его так:
def func[A, G[_], F[_]: LiftF[?[_], G]](a: F[A]): G[A]
Я хотел бы избавиться от части ?[_]
, поэтому мое первоначальное предположение состояло в том, чтобы написать тип To[G[_]]
, который возвращает LiftF[?[_], G]
, чтобы преобразовать приведенное выше определение функции в
def func[A, G[_], F[_]: LiftF.To[G]](a: F[A]): G[A]
Однако при записи определения типа To
как
type To[G[_]] = LiftF[?[_], G]
я получаю следующую ошибку компиляции:
Error:(17, 20) type Λ$ takes type parameters
type To[G[_]] = LiftF[?[_], G]
Попытка переписать его с экзистенциальными типами приводит к следующему определению типа:
type To[G[_]] = LiftF[F, G] forSome { type F[X] }
Это прекрасно компилируется, но, что не удивительно, не может быть применено к другим параметрам типа, поэтому определение желаемой функции не может быть достигнуто.
Мне удалось реализовать "частичное приложение""часть с кодом, вдохновленным шаблоном aux:
trait To[G[_]] {
type From[F[_]] = LiftF[F, G]
}
К сожалению, это оставляет меня с синтаксисом, который, возможно, хуже оригинального:
def func[A, G[_], F[_]: LiftF.To[G]#From](a: F[A]): G[A]
У меня вопрос - могу ли я добиться изначально предложенного синтаксиса в Scala с помощью доброжелательного проектора, или я должен просто придерживаться ?[_]
?