Введите лямбда с более высоким видом
В Дотти дано следующее:
object Domain {
final case class Create(name: String) extends BaseCreate[Create] {
override type Model = Domain
override def service[F[_]](client: KeystoneClient[F]): CrudService[F, Domain, Create] = client.domains
}
}
case class Domain(id: String)
class CrudService[F[_], Model, Create]
final class Domains[F[_]] extends CrudService[F, Domain, Domain.Create]
class KeystoneClient[F[_]] {
val domains = new Domains[F]
}
trait BaseCreate[Create <: BaseCreate[Create]] {
type Model
def service[F[_]](client: KeystoneClient[F]): CrudService[F, Model, Create]
}
Я хочу "упростить"
BaseCreate
так что я могу реализовать
Create
как это:
final case class Create(name: String) extends BaseCreate.Aux[Domain, Create](_.domains)
Я пытался:
object BaseCreate {
abstract class Aux[M, Create](f: [F[_]] =>> KeystoneClient[F] => CrudService[F, M, Create]) extends BaseCreate[Create] {
type Model = M
def service[F[_]](client: KeystoneClient[F]): CrudService[F, Model, Create] = f(client)
}
}
Но компилятор жалуется:
Missing type parameter for [F[_$5]] =>> KeystoneClient[F] => CrudService[F, M, Create]
Что для меня не имеет смысла. Какой правильный синтаксис, если он есть?
Ссылка на scastie с этим кодом
PS: Я не хочу вводить дополнительные параметры типа в
BaseCreate
. Особенно
F
так как это будет означать класс
Domain.Create
должен быть
final case class Create[F[_]]
что вовсе не является предполагаемым решением.
1 ответ
Думаю, вы перепутали лямбды типов с полиморфными функциями.
Лямбда типа отображает типы в типы, полиморфная функция отображает значения в значения, только тип ее аргумента может варьироваться.
Для лямбда-выражений типа вы должны использовать
=>>
, для полиморфных функций следует использовать обычные
=>
(дважды т.е.
[A] => (a: A) => f(a)
).
Так должно быть
object BaseCreate {
abstract class Aux[M, Create](f: [F[_]] => KeystoneClient[F] => CrudService[F, M, Create]) extends BaseCreate[Create] {
type Model = M
def service[F[_]](client: KeystoneClient[F]): CrudService[F, Model, Create] = f(client)
}
}
final case class Create(name: String) extends BaseCreate.Aux[Domain, Create](
[F[_]] => (client: KeystoneClient[F]) => client.domains
)
но он не компилируется в Dotty 0.28.0-bin-20200920-e99793e-NIGHTLY с ошибкой
Found: Object with PolyFunction {...}
Required: PolyFunction{
apply:
[F[_$6]]
(x$1: App.KeystoneClient[F]):
App.CrudService[F, App.Domain, App.Create]
}
[F[_]] => (client: KeystoneClient[F]) => client.domains
Кажется, это ошибка.