根据类型类设置抽象类型 [英] 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
.有没有办法说服编译器是这种情况?
Which gives me the error shown above. Unless I have failed to follow my own logic through correctly, this.aIsBaseTc.self
should resolve to a Double
. Is there a way to persuade the compiler that this is the case?
感谢您的帮助.
推荐答案
问题在范围内.
一个简单的例子是
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
,当调用 test
时, x
将被解析(在的范围内> test
呼叫站点),但在当前范围( test
定义范围)中定义了 a
.同样, aIsBaseTc
不是 doubleHoldsTypeMember
.
You assume that x
is a
(aIsBaseTc
is doubleHoldsTypeMember
in your notations). But actually x
is not a
, x
will be resolved when test
is called (in the scope of test
call site) but a
is defined in current scope (scope of test
definition). Similarly, aIsBaseTc
is not doubleHoldsTypeMember
.
使用隐式解析时类型参数,为什么val放置很重要?(请参见 implicit x:X
和 implicitly [X]
之间的区别.)
When doing implicit resolution with type parameters, why does val placement matter? (See the difference between implicit x: X
and implicitly[X]
.)
对于任何匿名课程
implicit val containerOfDoubleIsActual = new IsActualTC[Container[Double], Double] {
def get(self: Self) = self.get // type mismatch;
}
是
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
.
And since aIsBaseTc
is not doubleHoldsTypeMember
, aIsBaseTc.Self
is not Double
.
可能的解决方法是在 IsActualTC
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
}
这篇关于根据类型类设置抽象类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!