Scala 类型类和子类型
我有以下定义类型类的代码Scala 类型类和子类型,scala,typeclass,implicit,subtyping,Scala,Typeclass,Implicit,Subtyping,我有以下定义类型类的代码 trait Foo[T] { def toFoo(x: T): String } trait Foos { def toFoo[T](f: T => String): Foo[T] = new Foo[T] { def toFoo(x: T): String = f(x) } } object Foo extends Foos { def toFoo[A: Foo](a: A) = implicitly[Foo[A]].toFoo(a)
trait Foo[T] {
def toFoo(x: T): String
}
trait Foos {
def toFoo[T](f: T => String): Foo[T] = new Foo[T] {
def toFoo(x: T): String = f(x)
}
}
object Foo extends Foos {
def toFoo[A: Foo](a: A) = implicitly[Foo[A]].toFoo(a)
implicit def AToFoo: Foo[A] = toFoo { c =>
"A"
}
implicit def BToFoo[T]: Foo[B] = toFoo { c =>
"B"
}
implicit def ListToFoo[T: Foo]: Foo[List[T]] = toFoo { c =>
c.map(toFoo(_)).
}
}
class A
class B extends A
现在如果我有,如果我做了
toFoo(List(newa,newb)
我得到的是List(“A”,“A”)
而不是List(“A”,“B”)
。对于类型为B
的类,如何确保使用BtoFoo
方法而不是AToFoo
?隐式解析纯粹是一种编译时机制。这里区分子类型的简单方法是在隐式中进行匹配。完全删除BtoFoo
,并使用>一个
版本处理这两种情况
implicit val AIsFoo : Foo[A] = toFoo {
case b: B => "B"
case a: A => "A"
}
当然,也可以为层次结构的一部分委托给方法。您可以在a
中委托给方法,在B
中委托给方法,并且仍然具有用于列表的typeclass工作,在这里您不能添加方法
你也可以考虑声明<代码> Fo< <代码>反变量.< /p>你期望什么类型的代码>清单(新的A,新的B)<代码>?我希望代码>列表(new a,new b)< /c> >类型<代码>列表[a] < /COD>在这种情况下,当你映射<代码> ToFoO< <代码> > <代码>列表[A] < /代码>时,它显然最先执行<代码> [Fo[a] ]并获取
AToFoo
隐式定义,并将其用于每个元素。TypeClass是为类型定向分派而设计的,而不是为值定向分派而设计的,因此它们并不总是能很好地处理子类型。我已经使用模式匹配实现了您的建议,但在我看来,检查所有子类型似乎不是很优雅在AIsFoo
中A
的ren,而不是能够直接为A的任何孩子X
编写XIsFoo
。声明Foo
逆变如何工作?我尝试了trait Foo[-T]{def toFoo(X:T):String}