Как вы определяете HKT в Scala для предоставления методов, таких как map
, в качестве методов на экземплярах вместо функций на объектах?
Я знаю, что вы можете
trait M[F[_]] {
def map[A, B](f: F[A])(fn: A => B): F[B]
}
object Q extends M[Q] {
def map[A, B](f: Q[A])(fn: A => B) = new Q(fn(f.e))
}
class Q[A](val e: A)
Q.map(new Q(1))(_.toDouble)
Однако я хочу использовать map
на экземплярах вместо этого.Я не видел никакой литературы, которая делает это, поэтому я написал следующее.
trait M[A, F[A]] {
def map[B](f: A => B): F[B]
}
class Q[A](val e: A) extends M[A, Q] {
def map[B](f: A => B) = new Q(f(e))
}
new Q(1).map(_.toDouble)
Это идиоматическая Scala?Делает ли он то, что должен map
?Есть ли ограничения по сравнению с версией объекта выше?(Кроме того, с extends M[A, Q[A]]
он не скомпилируется - почему?)
Я видел
trait M[A] {
def map[B](f: A => B): M[B]
}
, но тогда Q
map
может вернуть class R[A] extends M[A]
что не желательно.