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

scala – 将函数的隐式转换链接到泛型类

发布时间:2020-12-16 18:13:08 所属栏目:安全 来源:网络整理
导读:我有以下代码,它应该采用函数A =布尔值(输入类型的通用)并通过链式隐式转换将其转换为通用特征Y [A]: val f: Int = Boolean = ???trait X[A] { def m1: Unit}implicit def toX[A](f: A = Boolean): X[A] = ???f.m1 // Workstrait Y[A] { def m2: Unit}impli
我有以下代码,它应该采用函数A =>布尔值(输入类型的通用)并通过链式隐式转换将其转换为通用特征Y [A]:

val f: Int => Boolean = ???

trait X[A] {
  def m1: Unit
}
implicit def toX[A](f: A => Boolean): X[A] = ???
f.m1  // Works

trait Y[A] {
  def m2: Unit
}
implicit def toY[T,A](x: T)(implicit toX: T => X[A]): Y[A] = ???
f.m2  // Won't compile

不幸的是,最后一行不会编译.

执行以下任何一项更改就足以使代码编译:

>转动X非泛型
>转Y非泛型
>使用输出类型的泛型函数替换源类型(输入类型上的泛型函数)(Int => A)
>用其他泛型类型替换源类型,例如Option [A],Seq [A]或Array [A]

基于此,我的结论是隐式转换链不起作用,因为源类型(输入类型的泛型函数)是通用的和逆变的中间和目标类型(X [A]和Y [A])是通用的.

关于如何解决这个问题的任何想法?

更新:最终代码缩进不仅可以处理作为源类型的函数,还可以处理其他类型(选项[A],Seq [A],A等).为了实现这一点,我们的想法是拥有toX函数的版本,将每种类型转换为X [A].然后只需要一个版本的toY.

解决方法

我想我有一个解决方案,请查看以下代码:

val f: Int => Boolean = _ => true

trait X[A] {
  def m1: Unit
}
implicit def funcToX[A](f: A => Boolean): X[A] = new X[A] {
  override def m1: Unit = println("Hello x")
}
f.m1  // Works

trait Y[A] {
  def m2: Unit
}
implicit def toY[T[_,_],A](x: T[A,Boolean])(implicit toX: T[A,Boolean] => X[A]): Y[A] = new Y[A] {
  override def m2: Unit = {
    x.m1
    println("Hello y")
  }
}
f.m2 // now works

我在这里使用更高级的kinded类型语法.它是scala语言的高级功能,我没有足够的经验来解释它.转换为Y应适用于任何只需要两个类型参数的类型(并且已定义转换为“toX”).

问题是你真的需要转换为Y在参数T上是通用的吗?也许它足以让它接受函数作为参数:

implicit def toY[A](x: A => Boolean)(implicit toX: (A => Boolean) => X[A]) = ???

您可以阅读有关更高级别的类型的更多信息,例如这篇文章:

Scala: Types of a higher kind

更新

以下问题作者要求我提出了以下解决方案:

type SingleGenericFun[T] = T => _

val f: SingleGenericFun[Int] = _ > 42
val g: Int = 42

trait X[A] {
  def m1: Unit
}
implicit def toX(f: SingleGenericFun[Int]): X[Int] = ???
implicit def toX(x: Int): X[Int] = new X[Int] {
  override def m1: Unit = println(x)
}
f.m1  // Works

trait Y[A] {
  def m2: Unit
}
implicit def toY2[T[_,_])(implicit toX: T[A,Boolean] => X[A]): Y[A] = new Y[A] {
  override def m2: Unit = {
    x.m1
    println("Hello y!")
  }
}
implicit def toY0[A](x: A)(implicit toX: A => X[A]): Y[A] = new Y[A] {
  override def m2: Unit = {
    x.m1
    println("Hello y!")
  }
}
implicit def toY1[T[_],A](x: T[A])(implicit toX: T[A] => X[A]): Y[A] = new Y[A] {
  override def m2: Unit = {
    x.m1
    println("Hello y")
  }
}
g.m2
f.m2  // Compile

它仍然不是最好的解决方案,因为需要提供3种(或更多种)技术上做同样事情的方法,我不知道如何产生它,也不是首先是否可能.

(编辑:李大同)

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

    推荐文章
      热点阅读