根据类型类设置抽象类型
Setting abstract type based on typeclass
我有这样一个例子:
abstract class IsBaseTC[A] { type Self }
abstract class JustHoldsTypeMember[A] extends IsBaseTC[A]
implicit val doubleHoldsTypeMember = new JustHoldsTypeMember[Double] { type Self = Double }
abstract class IsActualTC[A, T](implicit val aIsBaseTc: IsBaseTC[T]) extends IsBaseTC {
type Self = A
def get(self: A): aIsBaseTc.Self
}
case class Container[T](
get: T
)
implicit val containerOfDoubleIsActual = new IsActualTC[Container[Double], Double] {
def get(self: Self) = self.get // type mismatch;
// found self.get.type (with underlying type Double)
// required this.aIsBaseTc.self
}
这给了我上面显示的错误。除非我没能正确地遵循我自己的逻辑,否则 this.aIsBaseTc.self
应该解析为 Double
。有没有办法让编译器相信是这种情况?
感谢您的帮助。
确实都是双打,但这就是价值。不是同一类型。
def get(self: A)
请求的类型是aIsBaseTc.Self
,你的情况是doubleHoldsTypeMember.Self
当尝试访问 doubleHoldsTypeMember
的自我时,您会得到:
问题是,您无法创建 this.aIsBaseTc.Self
,因为它不可访问。
为了解决它,您可以尝试创建一个 Self
的实例,您可以在其中访问它:
abstract class IsBaseTC[A] { type Self; def createSelf(): Self }
abstract class JustHoldsTypeMember[A] extends IsBaseTC[A]
implicit val doubleHoldsTypeMember: JustHoldsTypeMember[Double] = new JustHoldsTypeMember[Double] {
type Self = Double
override def createSelf() = 3.14
}
并使用它:
implicit val containerOfDoubleIsActual: IsActualTC[Container[Double], Double] = new IsActualTC[Container[Double], Double] {
override def get(self: Self) = this.aIsBaseTc.createSelf()
override def createSelf() = ???
}
然后,当运行:
containerOfDoubleIsActual.get(Container(4.12))
它将打印:
3.14
创建于 doubleHoldsTypeMember
的 createSelf
事情在范围内。
更简单的例子是
trait A { type T }
implicit val a: A { type T = Int } = null
def test(implicit x: A): Unit = {
implicitly[x.T =:= Int] // doesn't compile, cannot prove that x.T =:= Int
}
您假设 x
是 a
(aIsBaseTc
在您的符号中是 doubleHoldsTypeMember
)。但实际上x
不是a
,x
会在调用test
时解析(在test
调用点范围内)而是a
在当前范围内定义(test
定义的范围)。同样,aIsBaseTc
不是 doubleHoldsTypeMember
。
(查看implicit x: X
和implicitly[X]
的区别。)
至于任何匿名 class
implicit val containerOfDoubleIsActual = new IsActualTC[Container[Double], Double] {
def get(self: Self) = self.get // type mismatch;
}
是 shorthand 为
class IsActualTCImpl extends IsActualTC[Container[Double], Double] {
def get(self: Self) = self.get // type mismatch;
// aIsBaseTc is not doubleHoldsTypeMember here
}
implicit val containerOfDoubleIsActual =
new IsActualTCImpl // implicit is resolved here
// aIsBaseTc becomes doubleHoldsTypeMember here
并且由于 aIsBaseTc
不是 doubleHoldsTypeMember
,aIsBaseTc.Self
不是 Double
。
可能的解决方法是在 IsActualTC
中再添加一个类型参数 S
abstract class IsActualTC[A, T, S](implicit val aIsBaseTc: IsBaseTC[T] {type Self = S}) extends IsBaseTC {
type Self = A
def get(self: A): S
}
implicit val containerOfDoubleIsActual = new IsActualTC[Container[Double], Double, Double] {
def get(self: Self) = self.get
}
或者对IsActualTC
的隐式参数添加类型细化
abstract class IsActualTC[A, T](implicit val aIsBaseTc: IsBaseTC[T] {type Self = T}) extends IsBaseTC {
type Self = A
def get(self: A): aIsBaseTc.Self
}
implicit val containerOfDoubleIsActual = new IsActualTC[Container[Double], Double] {
def get(self: Self) = self.get
}
我有这样一个例子:
abstract class IsBaseTC[A] { type Self }
abstract class JustHoldsTypeMember[A] extends IsBaseTC[A]
implicit val doubleHoldsTypeMember = new JustHoldsTypeMember[Double] { type Self = Double }
abstract class IsActualTC[A, T](implicit val aIsBaseTc: IsBaseTC[T]) extends IsBaseTC {
type Self = A
def get(self: A): aIsBaseTc.Self
}
case class Container[T](
get: T
)
implicit val containerOfDoubleIsActual = new IsActualTC[Container[Double], Double] {
def get(self: Self) = self.get // type mismatch;
// found self.get.type (with underlying type Double)
// required this.aIsBaseTc.self
}
这给了我上面显示的错误。除非我没能正确地遵循我自己的逻辑,否则 this.aIsBaseTc.self
应该解析为 Double
。有没有办法让编译器相信是这种情况?
感谢您的帮助。
确实都是双打,但这就是价值。不是同一类型。
def get(self: A)
请求的类型是aIsBaseTc.Self
,你的情况是doubleHoldsTypeMember.Self
当尝试访问 doubleHoldsTypeMember
的自我时,您会得到:
问题是,您无法创建 this.aIsBaseTc.Self
,因为它不可访问。
为了解决它,您可以尝试创建一个 Self
的实例,您可以在其中访问它:
abstract class IsBaseTC[A] { type Self; def createSelf(): Self }
abstract class JustHoldsTypeMember[A] extends IsBaseTC[A]
implicit val doubleHoldsTypeMember: JustHoldsTypeMember[Double] = new JustHoldsTypeMember[Double] {
type Self = Double
override def createSelf() = 3.14
}
并使用它:
implicit val containerOfDoubleIsActual: IsActualTC[Container[Double], Double] = new IsActualTC[Container[Double], Double] {
override def get(self: Self) = this.aIsBaseTc.createSelf()
override def createSelf() = ???
}
然后,当运行:
containerOfDoubleIsActual.get(Container(4.12))
它将打印:
3.14
创建于 doubleHoldsTypeMember
事情在范围内。
更简单的例子是
trait A { type T }
implicit val a: A { type T = Int } = null
def test(implicit x: A): Unit = {
implicitly[x.T =:= Int] // doesn't compile, cannot prove that x.T =:= Int
}
您假设 x
是 a
(aIsBaseTc
在您的符号中是 doubleHoldsTypeMember
)。但实际上x
不是a
,x
会在调用test
时解析(在test
调用点范围内)而是a
在当前范围内定义(test
定义的范围)。同样,aIsBaseTc
不是 doubleHoldsTypeMember
。
implicit x: X
和implicitly[X]
的区别。)
至于任何匿名 class
implicit val containerOfDoubleIsActual = new IsActualTC[Container[Double], Double] {
def get(self: Self) = self.get // type mismatch;
}
是 shorthand 为
class IsActualTCImpl extends IsActualTC[Container[Double], Double] {
def get(self: Self) = self.get // type mismatch;
// aIsBaseTc is not doubleHoldsTypeMember here
}
implicit val containerOfDoubleIsActual =
new IsActualTCImpl // implicit is resolved here
// aIsBaseTc becomes doubleHoldsTypeMember here
并且由于 aIsBaseTc
不是 doubleHoldsTypeMember
,aIsBaseTc.Self
不是 Double
。
可能的解决方法是在 IsActualTC
S
abstract class IsActualTC[A, T, S](implicit val aIsBaseTc: IsBaseTC[T] {type Self = S}) extends IsBaseTC {
type Self = A
def get(self: A): S
}
implicit val containerOfDoubleIsActual = new IsActualTC[Container[Double], Double, Double] {
def get(self: Self) = self.get
}
或者对IsActualTC
abstract class IsActualTC[A, T](implicit val aIsBaseTc: IsBaseTC[T] {type Self = T}) extends IsBaseTC {
type Self = A
def get(self: A): aIsBaseTc.Self
}
implicit val containerOfDoubleIsActual = new IsActualTC[Container[Double], Double] {
def get(self: Self) = self.get
}