型クラスを使用してF有界量化を回避する方法を説明するブログ(Scalaでの「現在の」型の戻りを参照)は、その終わり近くに言及しています。
ここでの問題は、の種類との間の接続点である
p._1
とはp._2
、コンパイラは、もはや彼らは正確に並ぶことを知っているので、この文脈で失われることはありません。これを修正する方法、および一般に存在の喪失を防ぐ方法は、パターンマッチを使用することです。
上記のコードが機能しないことを確認しました。
pets.map(p => esquire(p._1)(p._2))
他のパターンマッチングバリアントは次のことを行います。
pets.map { case (a, pa) => esquire(a)(pa) }
言及されていない別のバリアントもあり、これも機能します。
pets.map{case p => esquire(p._1)(p._2)}
ここの魔法は何ですか?存在する型情報case p =>
をp =>
保持する代わりに使用するのはなぜですか?
私はこれをScala2.12と2.13でテストしました。
コードで遊ぶためのScastieリンク:https://scastie.scala-lang.org/480It2tTS2yNxCi1JmHx8w
Scala 3(Dotty)では、実存型が存在しなくなったため(しゃれを意図したもの)、質問を変更する必要があります。case
別のscastieで示されているように、そこがなくても機能するようです:https://scastie.scala-lang.org/qDfIgkooQe6VTYOssZLYBg (case p
Scala 2.12 /2.13のヘルパークラスでもまだ必要かどうかを確認できます-それなしのコンパイルエラー)。
ヘルパーで変更されたコードcase class
:
case class PetStored[A](a: A)(implicit val pet: Pet[A])
val pets = List(PetStored(bob), PetStored(thor))
println(pets.map{case p => esquire(p.a)(p.pet)})
https://stackoverflow.com/a/49712407/5205022に基づいて、スニペットを検討してください
pets.map { p =>
val x = p._1
val y = p._2
esquire(x)(y)
}
型チェックは、後に-Xprint:typer
なると
Hello.this.pets.map[Any](((p: (A, example.Hello.Pet[A]) forSome { type A }) => {
val x: Any = p._1;
val y: example.Hello.Pet[_] = p._2;
Hello.this.esquire[Any](x)(<y: error>)
}))
パターンマッチングのあるスニペット
pets.map { case (a, pa) =>
val x = a
val y = pa
esquire(x)(y)
}
タイプチェック後
Hello.this.pets.map[Any](((x0$1: (A, example.Hello.Pet[A]) forSome { type A }) => x0$1 match {
case (_1: A, _2: example.Hello.Pet[A]): (A, example.Hello.Pet[A])((a @ _), (pa @ _)) => {
val x: A = a;
val y: example.Hello.Pet[A] = pa;
Hello.this.esquire[A](x)(y)
}
}));
後者のパターンマッチングの場合、実存型パラメーターA
が再導入されることに注意してください。
val x: A = a;
val y: example.Hello.Pet[A] = pa;
そして、の間の関係にx
し、y
失われた関係と一致するパターンがない場合にしながら、再確立され
val x: Any = p._1;
val y: example.Hello.Pet[_] = p._2;
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加