【问题标题】:How to handle frontier between typeclass and inheritance usage如何处理类型类和继承使用之间的边界
【发布时间】:2013-06-08 17:00:28
【问题描述】:

我很沮丧,因为我不知道如何处理我的类型安全代码和使用多态性和继承的外部 API 之间的边界。

我的流程如下。我收到 Class1 类的条目值,我用它从外部服务中检索 Class2 类的项目。然后我需要对两者进行子类型化以获得它们的运行时类型并解析隐式。但是,由于类型擦除,这是不可能的。

trait Typeclass1[A, B] {
  def hash(a: A, b: B): String
}

trait Typeclass2[A, B] {
  def hash(a: A, b: B): B
}

trait Entity

trait MyEntity1

trait MyEntity2

object db {
  def load(any:Any):Entity = new Entity{}
}


class MyClass[T](t: T, a: String) {

  def apply(timeout: Long): T = {
    val loadFromDB = db.load(t)
    loadFromDB match {
      case myEntity1: MyEntity1 => applyTypeSafe(myEntity1)
      case myEntity2: MyEntity2 => applyTypeSafe(myEntity2)
    }
  }


  def applyTypeSafe[C](c: C)(implicit typeClass1: Typeclass1[C, T], typeclass2: Typeclass2[C, T]): (String, T) = {
    typeClass1.hash(c, t) -> typeclass2.hash(c, t)
  }
}

我想知道开发这个前沿层的正确模式是什么。我可能需要一个类型构造函数来为我的类型类提供在 MyClass 的构造函数中......或者完全重新思考我的设计?

【问题讨论】:

  • 我没有看到问题。哪些类型会被删除?据我所知,您应该能够在 loadFromDB 上可靠地进行模式匹配,然后您已经恢复了 DB 层丢失的所有类型信息。

标签: scala typeclass


【解决方案1】:

如果在MyEntityMyEntity2 的范围内添加隐式定义,则不会出现编译问题。比如下面的代码编译就ok了:

trait Typeclass1[A, B] { def hash(a: A, b: B): String }
trait Typeclass2[A, B] { def hash(a: A, b: B): B }

trait Entity
trait MyEntity1 extends Entity
trait MyEntity2 extends Entity

object db { def load(any:Any):Entity = new Entity {} }

implicit def MyEntity1HasTypeclass1[T] = new Typeclass1[MyEntity1, T] {
  def hash(a: MyEntity1, t: T) = a.toString
}
implicit def MyEntity1HasTypeclass2[T] = new Typeclass2[MyEntity1, T] {
  def hash(a: MyEntity1, t: T) =t
}

class MyClass[T](t: T, a: String) {
  def apply(timeout: Long): (String, T) = {
    db.load(t) match {
      case myEntity1: MyEntity1 => applyTypeSafe(myEntity1)
    }
  }
  def applyTypeSafe[C](c: C)(implicit typeClass1: Typeclass1[C, T], 
                                      typeclass2: Typeclass2[C, T]): (String, T) = {
    typeClass1.hash(c, t) -> typeclass2.hash(c, t)
  }
}

【讨论】:

  • 只要您可以为 ALL T 提供 Typeclass1 和 Typeclass2 的通用构造函数,这就会起作用。但是如果您的类型类仅针对特定 T 存在呢?
  • 然后您可以为MyClass 参数添加一个上限:class MyClass[T <: Special] 或为applyTypeSafe 方法添加一个约束:def applyTypeSafe[C, S](c: C)(implicit ev: S =:= Special, typeClass1,...)
猜你喜欢
  • 2012-12-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-12
相关资源
最近更新 更多