gpt4 book ai didi

scala - If-Then-Else DSL - 定义隐式来区分两种返回类型

转载 作者:行者123 更新时间:2023-12-01 01:57:45 24 4
gpt4 key购买 nike

我正在尝试构建一个小型 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)
}

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

最佳答案

关于你较短的例子:

定义 implicit def GERes: Result[GE, IfGE]对应类型 GE没错,但是 WhiteNoise()有类型 WhiteNoise <: GE ,这不符合隐含的。

您可以更改隐式的定义以适用于 GE 的子类型。 :

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

或定义 Result在其第一个类型参数中是逆变的。这将使隐式也适用于子类型:
sealed trait Result[-A, Out]
object Result extends LowPri {
implicit def GERes: Result[GE, IfGE] = ???
}

关于scala - If-Then-Else DSL - 定义隐式来区分两种返回类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39036332/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com