【问题标题】:What is the simplest way to create given for A & B type?为 A & B 类型创建给定的最简单方法是什么?
【发布时间】:2022-01-25 19:07:07
【问题描述】:

我有

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 类型创建给定的最简单方法是什么

【问题讨论】:

    标签: scala implicit scala-3


    【解决方案1】:

    您可以通过在given 实例中嵌套using 子句来获得Foo & Bar,但是一旦您开始修改FooBar 中的值,结果可能不是您所期望的,因为FooBar 也是@987654326 @ 和 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 你应该避免与类型类的子类型关系,并在不扩展 FooBar 的情况下定义 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
    

    【讨论】:

      【解决方案2】:

      所以,在大家的帮助下,我认为最简单的解决方案是

      given (using f: Foo, b: Bar): Foo with Bar with 
        export f.*
        export b.*
      

      【讨论】:

        【解决方案3】:

        诚然,我没有直接的 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,这相当于 Scala 2:

        implicit def aAndB(implicit a: A, b: B) = new A with B {
          def foo: Int = a.foo
          def bar: Int = b.bar
        }
        

        【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-01-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-15
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多