在Scala中丢失类型信息和类型类实现

在Scala中丢失类型信息和类型类实现,scala,typeclass,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 clas

我有以下关系:

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] }
不使用
case
,因为它将打破拥有类型类以实现未来可扩展性的想法


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

在这个问题中可以看出两个主要的困难

  • 隐式由编译器解析。在有抽象类型但需要具体隐式的情况下,必须以某种方式将预缓存的typeclass实例带到结果代码中
  • 子类型抽象与类型类样式的抽象之间的关系非常糟糕。结合这些需要很多折衷和变通方法
  • 但让我们想象一下,我们有这样的定义

    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"
      }
    }
    
    现在您可以编写奇怪的代码,如

    val xs: List[MemoTC[Foo, Bar]] = List(MemoTC(A()), MemoTC(B()))
    xs.map(x => x.withTC( x ⇒ implicit bar ⇒ Doer(x) ))
    
    如果希望保持typeclass不变,还可以借助于存在类型对本例进行调整:

    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)))
    
    trait Bar[I]{def doSomething(x:I):String}
    对象实践者{
    def应用[I]
    
    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)))