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

scala – If-Then-Else DSL – 定义implicits以区分两种返回类型

发布时间:2020-12-16 10:00:59 所属栏目:安全 来源:网络整理
导读:我正在尝试构建一个小型DSL,允许一些if-then-else分支具有两种类型的组合,一种是通用的(If),另一种是具有附加功能的(IfGE).我的印象是,混合使用低优先级的隐式特征,我可以让 Scala为Else操作选择更精确的返回类型,但它失败了.这是建筑: 编辑:这是一个小例
我正在尝试构建一个小型DSL,允许一些if-then-else分支具有两种类型的组合,一种是通用的(If),另一种是具有附加功能的(IfGE).我的印象是,混合使用低优先级的隐式特征,我可以让 Scala为Else操作选择更精确的返回类型,但它失败了.这是建筑:

编辑:这是一个小例子.下面是对上下文的更全面的介绍.对于回答这个问题,可能只关注这个极小的情况就足够了,而要理解我正在做什么,更长的例子可能会更好.

trait GE
trait If[A] {
  def Else[B >: A,Out](cond: => B)(implicit result: Result[B,Out]): Out
}
trait IfGE extends If[GE] with GE

case class SinOsc()     extends GE
case class WhiteNoise() extends GE

trait LowPri {
  implicit def AnyRes[A]: Result[A,If[A]] = ???  // !
}
object Result extends LowPri {
  implicit def GERes: Result[GE,IfGE] = ???
}
sealed trait Result[A,Out]

def IfExample: If[SinOsc]

val res1: GE = IfExample.Else(WhiteNoise())
val res2: GE = IfExample.Else[GE,IfGE](WhiteNoise())

这里,res1的类型推断和隐式解析失败,而在res2中明确地放置类型使它工作.我需要让res1工作,即不指定类型参数.

更长的例子:

(1)带有一些含义的图元素使用数字作为图元素并应用二元运算符:

object GE {
  implicit def intIsGE   (x: Int   ): GE = ???
  implicit def doubleIsGE(x: Double): GE = ???

  implicit class GEOps(private val ge: GE) extends AnyVal {
    def <= (that: GE): GE = ???
    def >  (that: GE): GE = ???
    def &  (that: GE): GE = ???
    def poll(): Unit = ???
  }
}
trait GE

(2)分支结构:

object If {
  def apply(cond: => GE): IfBuilder = ???
}

trait IfBuilder {
  def Then [A](branch: => A): If[A]
}

trait If[A] {
  def Else: ElseBuilder[A]
  def ElseIf(cond: => GE): ElseIfBuilder[A]
}

trait IfGE extends If[GE] with GE

object ElseBuilder {
  trait LowPri {
    implicit def AnyRes[A]: Result[A,If[A]] = ???
  }
  object Result extends LowPri {
    implicit def GERes: Result[GE,IfGE] = ???
  }
  sealed trait Result[A,Out]
}
trait ElseBuilder[A] {
  def apply[B >: A,Out](b: => B)(implicit res: ElseBuilder.Result[B,Out]): Out
}

trait ElseIfBuilder[A] {
  def Then [B >: A](branch: => B): If[B]
}

(3)一些示例图元素:

case class Out(signal: GE)
case class SinOsc(freq: GE) extends GE
case class Dust(freq: GE) extends GE
case class WhiteNoise() extends GE

(4)测试套件:

trait Tests {
  def freq: GE

  // ---- Unit/Any result ----

  val res0 = If (freq > 600) Then {
    Out(SinOsc(freq))
  }

  val res1 = If (freq > 400 & freq <= 600) Then {
    Out(SinOsc(freq))
  } Else {
    freq.poll()
  }

  // ---- GE result ----

  val res2: GE = If (freq > 100) Then {
    SinOsc(freq)
  } Else {
    WhiteNoise()
  }

  val res3: GE = If (freq > 1000) Then {
    SinOsc(freq)
  } ElseIf (freq > 100) Then {
    Dust(freq)
  } Else {
    WhiteNoise()
  }

  Out(res3)
}

但最后两个测试(res2和res3)不起作用.返回类型显然不是IfGE,而只是If [GE].我该如何解决这个问题,以便最后两个例子找到GER而不是AnyRes?

解决方法

关于你的简短例子:

定义隐式def GERes:结果[GE,IfGE]完全对应于GE类型,但WhiteNoise()具有类型WhiteNoise<:GE,并且不适合隐式. 您可以更改隐式的定义以适用于GE的子类型:

object Result extends LowPri {
  implicit def GERes[T <: GE]: Result[T,IfGE] = ???
}

或者在第一个类型参数中将Result定义为逆变.这将使implicits也适用于子类型:

sealed trait Result[-A,Out]
object Result extends LowPri {
  implicit def GERes: Result[GE,IfGE] = ???
}

(编辑:李大同)

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

    推荐文章
      热点阅读