scala - Scala 中丢失类型信息和类型类实现

标签 scala typeclass

我有以下关系:

trait Bar[I <: Foo] { def doSomething(...) }
object Doer { def apply[I <: Foo](...)(implicit ev: Bar[I]) = ev.doSomething(...) } 

trait Foo

case class A(...) extends Foo
object A { implicit object Something extends Bar[A] }

case class B(...) extends Foo
object B { implicit object SomethingElse extends Bar[B] }

我有以下情况:

val xs: List[Foo] = ...
xs.map(x => Doer(x)) // implicit not found since no implementation for type Foo.

不使用case,因为它将打破为 future 可扩展性而拥有类型类的整个想法。

我需要做什么才能处理这种情况?

最佳答案

从问题中可以看出两个主要困难

  1. 隐式由编译器解决。当您有抽象类型但需要具体隐式时,您必须以某种方式将预缓存的类型类实例携带到结果代码中。
  2. 子类型化抽象与类型类风格的抽象关系很糟糕。将这些结合起来需要很多妥协和解决方法。

但是想象一下我们有这样的定义

trait Bar[+I] {def doSomething[J >: I](x: J): String}
object Doer {
  def apply[I <: Foo](el: I)(implicit ev: Bar[I]) = ev.doSomething(el)
}

trait Foo

case class A() extends Foo
object A {
  implicit object Something extends Bar[A] {
    def doSomething[X >: A](el: X) = "do A"
}
}

case class B() extends Foo
object B {
  implicit object SomethingElse extends Bar[B] {
     def doSomething[X >: B](el: X) = "do B"
  }
}

我们也许可以创建一些数据类型来保留已解析的隐式:

case class MemoTC[+Value, TC[+_]](value: Value)(implicit tc: TC[Value]) {
  def withTC[Result](action: (Value) ⇒ TC[Value] ⇒ Result): Result =
    action(value)(tc)
} 

现在你可以编写奇怪的代码了

val xs: List[MemoTC[Foo, Bar]] = List(MemoTC(A()), MemoTC(B()))
xs.map(x => x.withTC( x ⇒ implicit bar ⇒ Doer(x) ))

如果您想保持类型类不变,也可以在存在类型的帮助下修改此示例:

trait Bar[I] {def doSomething(x: I): String}
object Doer {
  def apply[I <: Foo](el: I)(implicit ev: Bar[I]) = ev.doSomething(el)
}

trait Foo

case class A() extends Foo
object A {
  implicit object Something extends Bar[A] {
    def doSomething(el: A) = "do A"
  }
}

case class B() extends Foo
object B {
  implicit object SomethingElse extends Bar[B] {
    def doSomething(el: B) = "do B"
  }
}

abstract class MemoTC[Abstract, TC[_]] {
  type Concrete <: Abstract
  val value: Concrete
  val inst: TC[Concrete]

  def withTC[Result](action: (Concrete) ⇒ TC[Concrete] ⇒ Result): Result =
    action(value)(inst)
}

object MemoTC {
  def apply[A, C <: A, TC[_]](v: C)(implicit tc: TC[C]) = new MemoTC[A, TC] {
    type Concrete = C
    val value = v
    val inst = tc
  }
}


val xs: List[MemoTC[Foo, Bar]] = List(MemoTC(A()), MemoTC(B()))
xs.map(x => x.withTC(x ⇒ implicit bar ⇒ Doer(x)))

关于scala - Scala 中丢失类型信息和类型类实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39321083/

相关文章:

java - 如何为 Scala ExecutionContexts 配置关闭策略?

java - 有没有不适合 java/scala 的类似 dbunit 的框架?

haskell - Haskell 类型类中的记录选择器

haskell - 为什么这个类型类只能用 "-XNoMonomorphismRestriction"编译?

haskell - 如何为通用向量创建列表同构实例?

scala - Akka Actors 可以替代服务层吗?

抽象函数中的 Scala 泛型

java - 获取 Scala 类型的 Java 反射表示

haskell - 在实例上下文中需要泛型实例(对于更高级的类型构造函数)

haskell - 如何用 'reflection' 包替换 ImplicitParams?