我有
trait Foo:
def foo: Int
trait Bar:
def bar: Int
given Foo with
def foo = 1
given Bar with
def bar = 1
我有一个函数foobar
type FooBar = Foo & Bar
def foobar(using FooBar) = ...
如果我已经给出了A和B ,那么为A & B
类型创建给定的最简单方法是什么
您可以通过在given
实例中嵌套using
子句来获得Foo & Bar
,但一旦您开始修改FooBar
中的值,结果可能与您预期的不一样,因为FooBar
也是Foo
和Bar
,并且事情开始变得递归:
trait FooBar extends Foo with Bar
given (using f: Foo, b: Bar): FooBar with
def foo = f.foo + 1
def bar = b.bar + 2
def fooBar(using fb: Foo & Bar) = (fb.foo, fb.bar)
def foo(using f: Foo) = f.foo
def bar(using b: Bar) = b.bar
@main def main() =
println(foo) //2
println(bar) //3
println(fooBar) //(3, 5)
IMO您应该避免与typeclass的子类型关系,并在不扩展Foo
和Bar
:的情况下定义FooBar
trait FooBar:
def foo: Int
def bar: Int
given (using f: Foo, b: Bar): FooBar with
def foo = f.foo + 1
def bar = b.bar + 2
所以,在大家的帮助下,我认为最简单的解决方案是
given (using f: Foo, b: Bar): Foo with Bar with
export f.*
export b.*
诚然,我没有直接的Scala 3经验,但最简单的解决方案可以归结为:
given aAndB(using a: A, b: B): A & B with {
def foo: Int = a.foo
def bar: Int = b.bar
}
您有效地将A和B粘合在一起,并进行适当的调度。
可以实现一个自动调度(当没有冲突时(的宏。
AFAICT,这将相当于Scala2:
implicit def aAndB(implicit a: A, b: B) = new A with B {
def foo: Int = a.foo
def bar: Int = b.bar
}