Самостоятельная аннотация для класса с более высоким родственным типом - PullRequest
2 голосов
/ 14 апреля 2020

Дано:

abstract class Databases[F[_]]

Как я могу заставить эту черту работать:

// Marker trait signalling the database plugin supports StaticRoles
trait StaticRoles { this: Databases[_] => }

Я хочу убедиться, что StaticRoles только смешано в классах, которые также расширяются Databases, однако меня не волнует конкретное значение параметра типа F.

Код возвращает:

error: _$1 takes no type parameters, expected: one

Что справедливо, однако возвращает ту же ошибку для :

trait StaticRoles { this: Databases[_[_]] => }

Я также пытался:

trait StaticRoles { this: Databases[({type T[X[_]]})#T] => }

, который дает ошибку:

error: kinds of the type arguments (AnyRef{type T[X[_]]}#T) do not conform to the expected kinds of the type parameters (type F) in class Databases.
       AnyRef{type T[X[_]]}#T's type parameters do not match type F's expected parameters:
       type X has one type parameter, but type _ has none

Ответы [ 2 ]

6 голосов
/ 14 апреля 2020

Правильным является

trait StaticRoles { this: (Databases[F] forSome { type F[_] }) => }

Есть ли сокращение для переменной типа 'm forSome {type m [O] <: UpperBound [O]} `in Scala? </a>

Не каждый экзистенциальный тип может быть выражен подчеркиванием или (в данном случае) может быть выражен подчеркиванием.

Существует также

trait StaticRoles { this: Databases[F forSome { type F[_] }] => }

, отличный от первого, но то же самое, что и

trait StaticRoles { this: Databases[Any] => }

, поскольку

implicitly[(Databases[F forSome { type F[_] }]) =:= Databases[Any]]

(Any на самом деле является полинородным).

Databases[Any] является подтипом Databases[F] forSome { type F[_] }

implicitly[Databases[Any] <:< (Databases[F] forSome { type F[_] })]

С проекциями типа (#) правильное значение равно

trait StaticRoles { this: Databases[({ type F[_] })#F] => }

Databases[({ type F[_] })#F] также является подтипом Databases[F] forSome { type F[_] } (несопоставимо с Databases[Any] для инварианта Databases) .

Среди этих трех типов Databases[F] forSome { type F[_] }, Databases[Any] и Databases[({ type F[_] })#F] только первый работает с

trait IO[_]

class Abc extends Databases[IO] with StaticRoles // compiles

//class Abc1 extends StaticRoles // doesn't compile
1 голос
/ 14 апреля 2020

Я думаю, что вы должны определить следующее:


  abstract class Databases[F[_]]

  trait StaticRoles[F[_]] { this: Databases[F] =>

    def abc: String
  }

  class Abc extends Databases[IO] with StaticRoles[IO] {
    override def abc: String = ???
  }

Примечание: если вы удалите Databases[IO] и просто определите вот так

class Abc extends StaticRoles[IO] {...}

Это не скомпилируется. Я думаю, что это то, чего вы хотите достичь

...