Я хочу написать класс типов, чтобы добавить некоторое поведение к универсальному типу.Однако я не могу понять, как это сделать;Я продолжаю сталкиваться с ошибкой, приведенной ниже.
Представьте, что у вас есть универсальный тип 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]
}
Теперь вы хотите добавить некоторое поведение в этот класс, например преобразовать его вStream[A]
.Расширение на основе классов типов может показаться целесообразным:
// 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)
}
}
}
Когда я сейчас пытаюсь использовать этот класс типов в своем коде, я получаю следующую ошибку в 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
работать?
Я видел много примеров, включающих классы типов и неявное преобразование, но до сих пор ни один из них не работал с универсальными типами..