4

この質問に答えようとして、次のコードを思いつきました。

    case class Monkey(bananas: Int) 
    case class Tree(rings: Int)
    case class Duck(quacks: Seq[String])

    implicit class IntLike(val x : Int) extends AnyVal

    implicit def monkey2Age(monkey: Monkey): IntLike = monkey.bananas / 1000
    implicit def tree2Age(tree: Tree): IntLike = tree.rings
    implicit def duck2Age(duck: Duck): IntLike = duck.quacks.size / 100000

    def purchaseCandles[A <% IntLike]()(implicit age : A) = {
      val asAge : IntLike = age
      println(s"I'm going to buy $asAge candles!")
    }              

    {
        implicit val guest = Tree(50)
        purchaseCandles()
    }

IntLikeは、これが に焦点を当てた問題ではないことを私に納得させるためだけにあることに注意してくださいInt

これは、暗黙の使用法が悪いとしても、かなり標準的なようであり、私はそれがうまく機能することを期待していました。ただし、purchaseCandles()REPL を呼び出すと、次のエラーが発生します。

エラー: あいまいな暗黙の値: 型 => scala.collection.generic.CanBuildFrom[String,Char,String] のオブジェクト Predef の値 StringCanBuildFrom と型 Tree の値 guest の両方が予想される型 A と一致します

私は一生、これがどのように当てはまるかを見ることができません。IntLikeA は、私が発明したばかりの型である のビュー バウンドを持つようにバインドされています。REPL は、使用可能な暗黙のビューがないことを確認します。

scala> 暗黙的に[Tree => IntLike]

res14: ツリー => IntLike = function1

しかし

scala> 暗黙的に[scala.collection.generic.CanBuildFrom[文字列、文字、文字列] => IntLike]

:18: エラー: scala.collection.generic.CanBuildFrom[String,Char,String] => IntLike から利用できる暗黙的なビューはありません。

では、どのようStringCanBuildFromに適切なタイプにすることができますか? コンパイラは複数の従属暗黙を解決できますか?そうでない場合、なぜこのエラーが表示されるのですか?

4

2 に答える 2

1

答えを試す前に、ここではまず縮小されたケースを示します。問題の原因であると思わpurchaseCandlesれるタイプについて、ヒントなしで呼び出していることに注意してください。A

object Foo

def test[A <% Foo.type](implicit bar: A) {}

test

エラー:

<console>:10: error: ambiguous implicit values:
 both value StringCanBuildFrom in object Predef of type =>
     scala.collection.generic.CanBuildFrom[String,Char,String]
 and method conforms in object Predef of type [A]=> <:<[A,A]
 match expected type A
              test
              ^

StringCanBuildFrom紛らわしいエラーメッセージのようです。ここに集中するconformsと、これが機能しない理由がより明確になる可能性がありPredef.conformます。暗黙の変換を要求するたびにA => A、これは ID によって保証されると述べています。これは、 がある場合、 の種類を定義する必要なく、型の値でdef foo[B <% A](b: B)いつでも呼び出すことができるようにするためです。fooAA => A


指定されていない型の暗黙の引数の解決と、その指定されていない型からへの変換を要求していIntLikeます。それは暗黙の解決アルゴリズムの範囲を超えていると思います。それでもエラーメッセージはやや奇妙です。

于 2013-03-15T14:14:34.243 に答える
0

失敗する理由はまだ説明されていませんが、前述のように、入力型が定義されていないため、これは暗黙の解決には多すぎると思いますが、次のように機能させることができます。

    implicit def findIntLike[A <% IntLike](x: A): IntLike = x
    def purchaseCandles()(implicit age: IntLike) = {
      println(s"I'm going to buy $age candles!")
    }              

    implicit val guest = Tree(50)
    purchaseCandles()
于 2013-03-15T14:32:47.527 に答える