【问题标题】:Curious error message regarding implicits关于隐式的奇怪错误消息
【发布时间】:2011-10-29 18:08:59
【问题描述】:
scala> implicit def transitive[A, B, C](implicit f: A => B, g: B => C): A => C = f andThen g
transitive: [A, B, C](implicit f: A => B, implicit g: B => C)A => C

scala> class Foo; class Bar; class Baz { def lol = println("lol") }
defined class Foo
defined class Bar
defined class Baz

scala> implicit def foo2Bar(f: Foo) = new Bar
foo2Bar: (f: Foo)Bar

scala> implicit def bar2Baz(f: Bar) = new Baz
bar2Baz: (f: Bar)Baz

scala> implicitly[Foo => Baz]
<console>:14: error: diverging implicit expansion for type Foo => Baz
starting with method transitive in object $iw
              implicitly[Foo => Baz]

从上面的代码中应该很明显,我正在尝试编写一个方法,当在范围内导入时,该方法将使隐式转换传递。我期待这段代码能够工作,但令人惊讶的是它没有。上面的错误信息是什么意思,我怎样才能使这段代码工作?

【问题讨论】:

    标签: scala implicit-conversion


    【解决方案1】:

    更新:如 cmets 所述,此方法无法在 2.8 上编译,虽然 implicitly[Foo =&gt; Baz] 可以正常工作,但 (new Foo).lol 不能。


    如果您将 transitive 重命名为 conforms 以隐藏 Predef 中的方法,则此方法效果很好:

    implicit def conforms[A, B, C](implicit f: A => B, g: B => C): A => C = f andThen g
    

    更多详情请见this answer


    附带说明:以-Xlog-implicits 启动REPL 是在这种情况下获取更多信息错误消息的便捷方式。在这种情况下,一开始并没有多大帮助:

    scala> implicitly[Foo => Baz]
    scala.this.Predef.conforms is not a valid implicit value for Foo => Baz because:
    type mismatch;
     found   : <:<[Foo,Foo]
     required: Foo => Baz
    <console>:14: error: diverging implicit expansion for type Foo => Baz
    starting with method transitive in object $iw
                  implicitly[Foo => Baz]
                            ^
    scala.this.Predef.conforms is not a valid implicit value for Foo => Baz because:
    type mismatch;
     found   : <:<[Foo,Foo]
     required: Foo => Baz
    transitive is not a valid implicit value for Unit => Foo => Baz because:
    not enough arguments for method transitive: (implicit f: A => B, implicit g: B => C)A => C.
    Unspecified value parameter g.
    transitive is not a valid implicit value for => Unit => Foo => Baz because:
    not enough arguments for method transitive: (implicit f: A => B, implicit g: B => C)A => C.
    Unspecified value parameter g.
    

    但如果我们暂时将 foo2Barbar2Baz 重写为函数,我们会收到一条错误消息,突出显示歧义:

    implicit val foo2Bar = (_: Foo) => new Bar
    implicit val bar2Baz = (_: Bar) => new Baz
    
    scala> implicitly[Foo => Baz]
    transitive is not a valid implicit value for Foo => Baz because:
    ambiguous implicit values:
     both method conforms in object Predef of type [A]=> <:<[A,A]
     and value foo2Bar in object $iw of type => Foo => Bar
     match expected type Foo => B
    

    现在很明显,我们只需要隐藏conforms

    【讨论】:

    • 感谢 Travis,但按照您的建议重命名后,它仍然对我不起作用。 ideone.com/KV0aY
    • @missingfaktor:它在 2.9.1 中对我有用。我去看看2.8。
    • 我在 2.9.1 上测试过。表达式 implicitly[Foo =&gt; Baz] 有效,但 (new Foo).lol 无效。
    • @missingfaktor:我不知道发生了什么。我添加了一个更新,表明这个答案并没有真正起作用。
    猜你喜欢
    • 2010-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多