根据类型类设置抽象类型 [英] Setting abstract type based on typeclass

查看:53
本文介绍了根据类型类设置抽象类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个这样的例子:

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆