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] = ??? } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
相关内容