使用类型类时类型不匹配

问题描述

我定义了一个这样的类型类:

/** Type class */
trait Drivable[V <: Vehicle]{
    def drive(v:V)
}

它请求Vehicle的子类型作为drive函数的参数。现在,我正在尝试将此类型类用于Vehicle本身。

/** ADT */
sealed trait Vehicle{
    def drive[V <: Vehicle](implicit d: Drivable[V]): Unit = d.drive(this)
}

编译器抱怨:

Error:(15,74) type mismatch;
 found   : Vehicle.this.type (with underlying type Vehicle)
 required: V
    def drive[V <: Vehicle](implicit d: Drivable[V]): Unit = d.drive(this)

如果我强制将this强制转换为V

def drive[V <: Vehicle](implicit d: Drivable[V]): Unit = d.drive(this.asInstanceOf[V])

但是我讨厌这样做。或者,如果我将它放在case类中,它也可以工作:

final case class Car(name:String) extends Vehicle {
    def drive(implicit d: Drivable[Car]): Unit = d.drive(this)
}

但是想象我有很多case classes,我必须在每个人中都重复一遍。

在基本特征中使用此类型类的正确方法是什么?

解决方法

drive用作扩展方法

sealed trait Vehicle

implicit class DrivableOps[V <: Vehicle](val vehicle: V) extends AnyVal {
  def drive(implicit d: Drivable[V]): Unit = d.drive(vehicle)
}

或将V设为特征的类型成员,而不是方法的类型参数

sealed trait Vehicle { 
  type V >: this.type <: Vehicle
  def drive(implicit d: Drivable[V]): Unit = d.drive(this)
}

case class Bus() extends Vehicle {
  override type V = Bus
}
case class Car() extends Vehicle {
  override type V = Car
}

类型V可以自动生成:

//libraryDependencies += "com.github.dmytromitin" %% "auxify-macros" % "0.8" 
import com.github.dmytromitin.auxify.macros.self 

@self sealed trait Vehicle { 
  def drive(implicit d: Drivable[Self]): Unit = d.drive(this) 
} 

@self case class Bus() extends Vehicle 
@self case class Car() extends Vehicle