【问题标题】:why implicit conversion doesn't work here?为什么隐式转换在这里不起作用?
【发布时间】:2013-06-04 02:56:17
【问题描述】:

我有这种代码

trait Outer1 {
  type Inner1
}

trait Outer2 {
  type Inner2

  val ev: Outer1#Inner1 =:= Inner2

  def f: Outer1#Inner1
}


object Main {

//  My Problem here  
//  def test1(o2: Outer2): o2.Inner2 =
//    o2.f                                  // <- type mismatch

  def test2(o2: Outer2): o2.Inner2 =
    o2.ev.apply(o2.f)
}

有没有机会让 test1 工作?为什么 Scala 编译器看不到 ev 并隐式应用它?

【问题讨论】:

    标签: scala implicit-conversion


    【解决方案1】:

    两个问题:首先,您的证据参数不是隐式的,因此编译器也不会隐式发现:

    trait Outer1 {
      type Inner1
    }
    
    trait Outer2 {
      type Inner2
    
      implicit val ev: Outer1#Inner1 =:= Inner2
    
      def f: Outer1#Inner1
    }
    

    第二个问题,一个值的成员是not part of the standard implicit lookup scope。所以你需要导入:

    object Main {
      def test1(o2: Outer2): o2.Inner2 = {
        import o2.ev  // !
        o2.f
      }
    }
    

    编辑:尽管有抽象类型检查,如果我没记错的话,你实际上无法实现 Outer2,因为你将如何给出当Inner1 是抽象的时,它的成员Inner2 等于Outer1#Inner1 的证据?这就是我要求具体场景的原因,因为从这个抽象的布局来看,我不确定你会到达任何地方。

    据我所知,证据只对依赖类型有意义,例如

    trait Outer1 {
      type Inner1
      def bar: Inner1
    }
    
    trait Outer2 {
      type Inner2
      val outer1: Outer1 { type Inner1 = Inner2 }
    
      def foo: Inner2 = outer1.bar
    }
    

    【讨论】:

    • 嗯,第一个问题是我的错,我同意。第二个真的让我难过:我看不出显式使用ev(如test2)和显式导入ev(如你的回答)之间有任何有价值的区别。我认为这是隐式查找机制中的设计缺陷。
    • 解决方案是将您的隐式放在编译器查找它们的位置,因此链接。通常这将是伴随对象,但实际的解决方案很大程度上取决于您的用例会是什么样子,从示例中很难判断。也许你反过来用另一种方式表述问题——更抽象地陈述你想要达到的目标,然后询问如何到达那里。
    • 我只希望我的方法在Outer2 中,它一定会返回Inner2 对象,以便在自身内部使用一些真正返回Inner1 的代码。我不希望任何额外的限定/导入指向编译器有证据表明Inner1 =:= Inner2:我通过ev 值声明的事实。我想知道在哪里放置 ev 以确保编译器无需额外帮助就能找到它。
    猜你喜欢
    • 2013-09-28
    • 1970-01-01
    • 2015-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-30
    • 1970-01-01
    相关资源
    最近更新 更多