Rah*_*thy 5 scala higher-kinded-types
我正在用更高级的类型浸泡我的脚趾,探索一个非常基本的Scala示例:
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", _))
Run Code Online (Sandbox Code Playgroud)
这有效:
bananaTuple(Option(42)) // Some((banana,42))
bananaTuple(Seq(42)) // List((banana,42))
Run Code Online (Sandbox Code Playgroud)
但这不编译:
bananaTuple(Some(42))
bananaTuple(List(42))
Run Code Online (Sandbox Code Playgroud)
我得到的编译错误:
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))
Run Code Online (Sandbox Code Playgroud)
如何在游戏中带来变化?
我们可以通过更多的参数多态性来完成这项工作:
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", _)))
}
}
Run Code Online (Sandbox Code Playgroud)
产量:
List((banana,1), (banana,2), (banana,3))
Some((banana,1))
Run Code Online (Sandbox Code Playgroud)
编译器现在推断出SomeasMappable[Some]#Res[Int]和 ,Mappable[List]#Res[Int]这非常难看。人们期望编译器实际上能够推断出正确的类型,而不需要特征上的任何协变/逆变Mappable,但我们不能这样做,因为我们在不变的位置使用它。
| 归档时间: |
|
| 查看次数: |
367 次 |
| 最近记录: |