Scala 类型 class 以扩展泛型类型:未找到参数的隐式
Scala type class to extend generic type: No implicits found for parameter
我想编写一个类型 class,为泛型类型添加一些行为。但是,我不知道该怎么做;我将 运行 保留在下面的错误中。
假设你有一个泛型 MyList[A]
:
trait MyList[A]
object MyList {
case class Empty[A]() extends MyList[A]
case class Node[A](value: A, next: MyList[A]) extends MyList[A]
}
现在您想为此 class 添加一些行为,例如将其转换为 Stream[A]
。基于类型 class 的扩展似乎是合适的:
// inspired by https://scalac.io/typeclasses-in-scala
trait MyListExt[T, A <: MyList[T]] {
def stream(a: A): Stream[T]
}
object MyListExt {
def apply[T, A <: MyList[T]](implicit a: MyListExt[T, A]): MyListExt[T, A] = a
object ops {
implicit class MyListExtOps[T, A <: MyList[T]](val a: A) extends AnyVal {
def stream(implicit ext: MyListExt[T, A]): Stream[T] = ext.stream(a)
}
}
private type T0
implicit val myListToStreamImpl: MyListExt[T0, MyList[T0]] = new MyListExt[T0, MyList[T0]] {
override def stream(a: MyList[T0]): Stream[T0] = {
def fold[T1](l: MyList[T1], acc: Stream[T1]): Stream[T1] = l match {
case MyList.Empty() => acc
case MyList.Node(value, next) => fold(next, acc :+ value)
}
fold(a, Stream.empty)
}
}
}
当我现在尝试在我的代码中使用这种类型 class 时,我在 l.stream
处收到以下错误:
No implicits found for parameter ext: MyListExt[T_, MyList[Int]]
object MyListTest {
def main(args: Array[String]): Unit = {
import MyListExt.ops._
val l: MyList[Int] = MyList.Node(1, MyList.Node(2, MyList.Node(3, MyList.Empty())))
l.stream.foreach(println)
}
}
我哪里做错了,或者我怎样才能让我的 l.stream
正常工作?
我已经看到很多涉及类型 classes 和隐式转换的示例,但是 none 到目前为止在泛型上运行。
implicit def myListToStreamImpl[T]: MyListExt[T, MyList[T]] = new MyListExt[T, MyList[T]] {
override def stream(a: MyList[T]): Stream[T] = {
def fold(l: MyList[T1], acc: Stream[T1]): Stream[T1] = l match {
case MyList.Empty() => acc
case MyList.Node(value, next) => fold(next, acc :+ value)
}
fold(a, Stream.empty[T1])
}
}
您的类型不一致,因为您出于某种奇怪的原因使用了 private type
。嵌套在对象中的类型具有完全不同的应用,它们与您当前的用例无关。
问题在于 l.stream.foreach(println)
中 l
被隐式转换为 new MyListExt.ops.MyListExtOps[.., ..](l)
并且泛型被推断为 [Nothing, MyList[Int]]
,这不满足 [T, A <: MyList[T]]
.
我看不出用 T
和 A <: MyList[T]
参数化 MyListExt
的理由。我猜 T
就够了,用 MyList[T]
代替 A
.
不要使用 private type T0
,只需使用 T0
又名 T
.
参数化 myListToStreamImpl
(使其成为 def
)
尝试
trait MyList[A]
object MyList {
case class Empty[A]() extends MyList[A]
case class Node[A](value: A, next: MyList[A]) extends MyList[A]
}
trait MyListExt[T] {
def stream(a: MyList[T]): Stream[T]
}
object MyListExt {
def apply[T](implicit a: MyListExt[T]): MyListExt[T] = a
object ops {
implicit class MyListExtOps[T](val a: MyList[T]) extends AnyVal {
def stream(implicit ext: MyListExt[T]): Stream[T] = ext.stream(a)
}
}
implicit def myListToStreamImpl[T]: MyListExt[T] = new MyListExt[T] {
override def stream(a: MyList[T]): Stream[T] = {
def fold[T1](l: MyList[T1], acc: Stream[T1]): Stream[T1] = l match {
case MyList.Empty() => acc
case MyList.Node(value, next) => fold(next, acc :+ value)
}
fold(a, Stream.empty)
}
}
}
object MyListTest {
def main(args: Array[String]): Unit = {
import MyListExt.ops._
val l: MyList[Int] = MyList.Node(1, MyList.Node(2, MyList.Node(3, MyList.Empty())))
l.stream.foreach(println)
}
}
我想编写一个类型 class,为泛型类型添加一些行为。但是,我不知道该怎么做;我将 运行 保留在下面的错误中。
假设你有一个泛型 MyList[A]
:
trait MyList[A]
object MyList {
case class Empty[A]() extends MyList[A]
case class Node[A](value: A, next: MyList[A]) extends MyList[A]
}
现在您想为此 class 添加一些行为,例如将其转换为 Stream[A]
。基于类型 class 的扩展似乎是合适的:
// inspired by https://scalac.io/typeclasses-in-scala
trait MyListExt[T, A <: MyList[T]] {
def stream(a: A): Stream[T]
}
object MyListExt {
def apply[T, A <: MyList[T]](implicit a: MyListExt[T, A]): MyListExt[T, A] = a
object ops {
implicit class MyListExtOps[T, A <: MyList[T]](val a: A) extends AnyVal {
def stream(implicit ext: MyListExt[T, A]): Stream[T] = ext.stream(a)
}
}
private type T0
implicit val myListToStreamImpl: MyListExt[T0, MyList[T0]] = new MyListExt[T0, MyList[T0]] {
override def stream(a: MyList[T0]): Stream[T0] = {
def fold[T1](l: MyList[T1], acc: Stream[T1]): Stream[T1] = l match {
case MyList.Empty() => acc
case MyList.Node(value, next) => fold(next, acc :+ value)
}
fold(a, Stream.empty)
}
}
}
当我现在尝试在我的代码中使用这种类型 class 时,我在 l.stream
处收到以下错误:
No implicits found for parameter ext: MyListExt[T_, MyList[Int]]
object MyListTest {
def main(args: Array[String]): Unit = {
import MyListExt.ops._
val l: MyList[Int] = MyList.Node(1, MyList.Node(2, MyList.Node(3, MyList.Empty())))
l.stream.foreach(println)
}
}
我哪里做错了,或者我怎样才能让我的 l.stream
正常工作?
我已经看到很多涉及类型 classes 和隐式转换的示例,但是 none 到目前为止在泛型上运行。
implicit def myListToStreamImpl[T]: MyListExt[T, MyList[T]] = new MyListExt[T, MyList[T]] {
override def stream(a: MyList[T]): Stream[T] = {
def fold(l: MyList[T1], acc: Stream[T1]): Stream[T1] = l match {
case MyList.Empty() => acc
case MyList.Node(value, next) => fold(next, acc :+ value)
}
fold(a, Stream.empty[T1])
}
}
您的类型不一致,因为您出于某种奇怪的原因使用了 private type
。嵌套在对象中的类型具有完全不同的应用,它们与您当前的用例无关。
问题在于 l.stream.foreach(println)
中 l
被隐式转换为 new MyListExt.ops.MyListExtOps[.., ..](l)
并且泛型被推断为 [Nothing, MyList[Int]]
,这不满足 [T, A <: MyList[T]]
.
我看不出用 T
和 A <: MyList[T]
参数化 MyListExt
的理由。我猜 T
就够了,用 MyList[T]
代替 A
.
不要使用 private type T0
,只需使用 T0
又名 T
.
myListToStreamImpl
(使其成为 def
)
尝试
trait MyList[A]
object MyList {
case class Empty[A]() extends MyList[A]
case class Node[A](value: A, next: MyList[A]) extends MyList[A]
}
trait MyListExt[T] {
def stream(a: MyList[T]): Stream[T]
}
object MyListExt {
def apply[T](implicit a: MyListExt[T]): MyListExt[T] = a
object ops {
implicit class MyListExtOps[T](val a: MyList[T]) extends AnyVal {
def stream(implicit ext: MyListExt[T]): Stream[T] = ext.stream(a)
}
}
implicit def myListToStreamImpl[T]: MyListExt[T] = new MyListExt[T] {
override def stream(a: MyList[T]): Stream[T] = {
def fold[T1](l: MyList[T1], acc: Stream[T1]): Stream[T1] = l match {
case MyList.Empty() => acc
case MyList.Node(value, next) => fold(next, acc :+ value)
}
fold(a, Stream.empty)
}
}
}
object MyListTest {
def main(args: Array[String]): Unit = {
import MyListExt.ops._
val l: MyList[Int] = MyList.Node(1, MyList.Node(2, MyList.Node(3, MyList.Empty())))
l.stream.foreach(println)
}
}