E不是一个法律的路径,因为它不是一个具体类型(Scala 3)

js81xvg6  于 4个月前  发布在  Scala
关注(0)|答案(2)|浏览(62)

我尝试将一个库从Scala 2.13迁移到Scala 3,但现有代码无法编译。
这里有一个片段

trait Identity
trait Authenticator

trait Env {
  type I <: Identity
  type A <: Authenticator
}

trait IdentityService[T <: Identity]
trait AuthenticatorService[T <: Authenticator]

trait Environment[E <: Env] {
  def identityService[T <: Identity]: IdentityService[E#I]
  def authenticatorService: AuthenticatorService[E#A]
}

字符串
Scala 3编译器失败:

error] 14 |  def identityService[T <: Identity]: IdentityService[E#I]
[error]    |                                                      ^
[error]    |                                         E is not a legal path
[error]    |                                         since it is not a concrete type
[error] -- Error: 
[error] 15 |  def authenticatorService: AuthenticatorService[E#A]
[error]    |                                                 ^
[error]    |                                         E is not a legal path
[error]    |                                         since it is not a concrete type
[error] two errors found


您可以直接在https://scastie.scala-lang.org/GuqSqC9yQS6uMiw9wyKdQg尝试

csbfibhn

csbfibhn1#

您可以使用match types(出于技术原因,也可以使用Aux-pattern,即细化类型Env { type I = i }不能是类型模式)

trait Env:
  type I <: Identity
  type A <: Authenticator
object Env:
  type AuxI[_I <: Identity] = Env { type I = _I }
  type AuxA[_A <: Authenticator] = Env { type A = _A }

trait IdentityService[T <: Identity]
trait AuthenticatorService[T <: Authenticator]

// match types
type I[E <: Env] <: Identity = E match
  case Env.AuxI[i] => i // lower case is significant

type A[E <: Env] <: Authenticator = E match
  case Env.AuxA[a] => a

trait Environment[E <: Env]:
  def identityService[T <: Identity]: IdentityService[I[E]]
  def authenticatorService: AuthenticatorService[A[E]]

字符串
What does Dotty offer to replace type projections?
In Scala 3, how to replace General Type Projection that has been dropped?
https://users.scala-lang.org/t/converting-code-using-simple-type-projections-to-dotty/6516
或者,您可以使用类型类。

nmpmafwu

nmpmafwu2#

下面是一个使用路径依赖类型的解决方案:

//> using scala 3

trait Identity
trait Authenticator

trait Env {
  type I <: Identity
  type A <: Authenticator
}

trait IdentityService[I <: Identity]
trait AuthenticatorService[A <: Authenticator]

trait Environment[E <: Env](using val env: E) {
  def identityService: IdentityService[env.I]
  def authenticatorService: AuthenticatorService[env.A]
}

字符串

相关问题