加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

Scala更高的kinded类型方差

发布时间:2020-12-16 18:36:54 所属栏目:安全 来源:网络整理
导读:我正在用更高级的类型浸泡我的脚趾,探索一个非常基本的 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)
我正在用更高级的类型浸泡我的脚趾,探索一个非常基本的 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",_))

这有效:

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))

如何在游戏中带来变化?

解决方法

我们可以使用更多参数多态来完成这项工作:

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),3))
Some((banana,1))

编译器现在将Some推断为Mappable [Some] #Res [Int]和Mappable [List] #Res [Int],这非常难看.人们可以期望编译器实际上能够推断出正确的类型,而不需要对Mappable特性进行任何协变/反演,这是我们无法做到的,因为我们在不变的位置使用它.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读