如何用scala在容器类型上编写typeclass,从容器返回元素?
在下面的程序中,我试图让typeclass工作。typeclass是Algo,它的实际实现需要一个容器[\up>编译:如何用scala在容器类型上编写typeclass,从容器返回元素?,scala,typeclass,Scala,Typeclass,在下面的程序中,我试图让typeclass工作。typeclass是Algo,它的实际实现需要一个容器[\up>编译: trait Algo[T, C <: Container[T]] { def algo(t : C) : Option[T] } object Algo { implicit def impl[T <: Id, C <: Container[T]] = new Algo[T,C] { def algo(cont : C) :
trait Algo[T, C <: Container[T]] {
def algo(t : C) : Option[T]
}
object Algo {
implicit def impl[T <: Id, C <: Container[T]] = new Algo[T,C] {
def algo(cont : C) : Option[T] = {
Some(cont.value)
}
}
implicitly[Algo[ElementWithId,Container[ElementWithId]]].algo(new Container[ElementWithId] {
override val value = new ElementWithId
})
}
trait Algo[T,C编译:
trait Algo[T, C <: Container[T]] {
def algo(t : C) : Option[T]
}
object Algo {
implicit def impl[T <: Id, C <: Container[T]] = new Algo[T,C] {
def algo(cont : C) : Option[T] = {
Some(cont.value)
}
}
implicitly[Algo[ElementWithId,Container[ElementWithId]]].algo(new Container[ElementWithId] {
override val value = new ElementWithId
})
}
trait Algo[T,C您的第一个问题是,在您的Algo实现中,您返回value
,它被声明为T
类型,但期望它是T#Elem
(您的意思可能是cont.Elem
,更准确)。类型恰好相同,但编译器不会检查。如果您声明val value:ElemType
,则可以开始执行某个操作
如果同时使用类型参数T和类型成员ElemType,则会带来很多复杂性,您也应该选择其中一个
trait Container[T <: Element] {
val value : T // might be wiser to avoid abstract val and prefer abstract def
}
我宁愿选择第一个。
因此,正确编写Algo将是
trait Algo[C[X <: Element] <: Container[X]] {
def algo[A <: Element](c: C): Option[A]
}
trait Algo[C[X您的第一个问题是,在您的Algo实现中,您返回值
,该值被声明为T
类型,但期望它是T#Elem
(您的意思可能是cont.Elem
,更准确)。类型恰好相同,但编译器不会检查。如果您声明val value:ElemType
,则可以开始执行某个操作
如果同时使用类型参数T和类型成员ElemType,则会带来很多复杂性,您也应该选择其中一个
trait Container[T <: Element] {
val value : T // might be wiser to avoid abstract val and prefer abstract def
}
我宁愿选择第一个。
因此,正确编写Algo将是
trait Algo[C[X <: Element] <: Container[X]] {
def algo[A <: Element](c: C): Option[A]
}
trait算法[C][X谢谢你的回答!但是我忘了添加要求,你能告诉我问题中的更新部分是否也可以吗?谢谢你的回答!但是我忘了添加要求,你能告诉我问题中的更新部分是否也可以吗?谢谢你的回答!但是我忘了添加要求,你能告诉我r问题中的更新部分也是可能的?@MHOOO是的,只是删除你不想要的边界。(参见更新的答案)奇怪,它对我不起作用。我得到(在注释中不起作用…:[错误]测试。scala:118:类型参数[T]不符合trait容器的类型参数边界[T@mhoo可能是这样,但是如果您想要一个容器[T哦,这是对的。那么有没有办法让容器本身成为一种类型,这样我就可以完全从Algo特性中摆脱对它的依赖?谢谢你的回答!但是我忘了添加一个要求,你能告诉我问题中的更新部分是否也可能吗?@mhoo是的,只要去掉你没有的边界就行了want.(参见更新的答案)奇怪,它对我不起作用。我得到(不在注释中工作…:[error]测试。scala:118:类型参数[T]不符合trait容器的类型参数边界[T@MHOOO可能是,但如果您想要容器哦,这是对的。那么,有没有办法让容器本身成为一个类型,这样我就可以完全从Algo特性中摆脱对它的依赖?
trait Algo[A <: Element, C <: C[A]] {
def algo(c: C[A]): Option[A]
}
trait Algo[R <: ElementType, C[X <: R] <: Container[X]] {
def algo[A <: R](c: C[A]): Option[A]
}
trait Algo4[R, C[X <: Element with R] <: Container[X]] {
def algo[A <: Element with R] (c: C[A]) : Option[A]
}