Scala更高种类的类型差异 [英] Scala higher kinded type variance
本文介绍了Scala更高种类的类型差异的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我将脚趾浸入更高种类的手指中,探索一个非常基本的Scala示例:
I am dipping my toes in higher kinded types, exploring a very basic Scala example:
trait Mappable[F[_]] {
def map[A, B](fa: F[A])(f: A => B): F[B]
}
object Mappable {
implicit object MappableOption extends Mappable[Option] {
def map[A, B](fa: Option[A])(f: A => B): Option[B] = fa.map(f)
}
implicit object MappableSeq extends Mappable[Seq] {
def map[A, B](fa: Seq[A])(f: A => B): Seq[B] = fa.map(f)
}
}
def bananaTuple[F[_], T](f: F[T])(implicit F: Mappable[F]): F[(String, T)] =
F.map(f)(("banana", _))
这有效:
bananaTuple(Option(42)) // Some((banana,42))
bananaTuple(Seq(42)) // List((banana,42))
但这无法编译:
bananaTuple(Some(42))
bananaTuple(List(42))
我得到的编译错误:
could not find implicit value for parameter F: ch.netzwerg.hkt.HigherKindedTypes.Mappable[Some] bananaTuple(Some(42))
not enough arguments for method bananaTuple: (implicit F: ch.netzwerg.hkt.HigherKindedTypes.Mappable[Some])Some[(String, Int)]. Unspecified value parameter F. bananaTuple(Some(42))
如何为游戏带来差异?
推荐答案
我们可以使用更具参数性的多态性使这项工作生效:
We can make this work with a little more parameteric polymorphism:
object MappableExample {
trait Mappable[F[_]] {
type Res[_]
def map[A, B](f: A => B)(c: F[A]): Res[B]
}
implicit def seqMappable[C[X] <: Seq[X]] = new Mappable[C] {
type Res[X] = Seq[X]
override def map[A, B](f:A => B)(c: C[A]): Seq[B] = c.map(f)
}
implicit def optionMappable[C[X] <: Option[X]]: Mappable[C] = new Mappable[C] {
type Res[X] = Option[X]
override def map[A, B](f: A => B)(c: C[A]): Option[B] = c.map(f)
}
def map[A, B, C[_]](xs: C[A])(f: A => B)(implicit mappable: Mappable[C]): mappable.Res[B] = {
mappable.map(f)(xs)
}
def main(args: Array[String]): Unit = {
println(map(List(1,2,3))(("banana", _)))
println(map(Some(1))(("banana", _)))
}
}
收益:
List((banana,1), (banana,2), (banana,3))
Some((banana,1))
编译器现在将Some
推断为Mappable[Some]#Res[Int]
和Mappable[List]#Res[Int]
,这非常难看.人们会希望编译器实际上能够推断出正确的类型,而无需Mappable
特征的任何协方差/协方差,这是我们无法做的,因为我们在不变的位置使用它.
The compiler now infers Some
as Mappable[Some]#Res[Int]
and Mappable[List]#Res[Int]
which is quite ugly. One would expect the compiler to actually be able to infer the right type without needing for any co/contravariance on the Mappable
trait, which we can't do since we're using it in an invariant position.
这篇关于Scala更高种类的类型差异的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文