Scalaでimplicitを連鎖させるには?
2023-08-10 07:50:33
質問
pimp-my-library パターンは、クラスからそのメソッドを実装するクラスへの暗黙の変換を利用可能にすることで、クラスにメソッドを追加するように見せかけることができます。
Scala はこのような暗黙の変換を二つ行うことを許しません.
A
から
C
を使用して、暗黙の
A
から
B
と、もう一つの暗黙の
B
から
C
. この制限を回避する方法はありますか?
どのように解決するのですか?
Scalaでは、メソッドを追加するための自動変換に制限があり、メソッドを探そうとしても複数の変換を適用しないようになっています。例えば
class A(val n: Int)
class B(val m: Int, val n: Int)
class C(val m: Int, val n: Int, val o: Int) {
def total = m + n + o
}
// This demonstrates implicit conversion chaining restrictions
object T1 { // to make it easy to test on REPL
implicit def toA(n: Int): A = new A(n)
implicit def aToB(a: A): B = new B(a.n, a.n)
implicit def bToC(b: B): C = new C(b.m, b.n, b.m + b.n)
// won't work
println(5.total)
println(new A(5).total)
// works
println(new B(5, 5).total)
println(new C(5, 5, 10).total)
}
EDIT: Scala 2.11からビュー境界('<%')は非推奨になりました。 https://issues.scala-lang.org/browse/SI-7629 (代わりに型クラスが使えます)
ただし,暗黙の定義が暗黙のパラメータ自身を必要とする場合(View bound),Scalaでは は は必要な限り追加の暗黙の値を探します。最後の例から続ける。
// def m[A <% B](m: A) is the same thing as
// def m[A](m: A)(implicit ev: A => B)
object T2 {
implicit def toA(n: Int): A = new A(n)
implicit def aToB[A1 <% A](a: A1): B = new B(a.n, a.n)
implicit def bToC[B1 <% B](b: B1): C = new C(b.m, b.n, b.m + b.n)
// works
println(5.total)
println(new A(5).total)
println(new B(5, 5).total)
println(new C(5, 5, 10).total)
}
マジックだ!」と言われるかもしれません。そうではありません。以下は、コンパイラがそれぞれをどのように翻訳するかです。
object T1Translated {
implicit def toA(n: Int): A = new A(n)
implicit def aToB(a: A): B = new B(a.n, a.n)
implicit def bToC(b: B): C = new C(b.m, b.n, b.m + b.n)
// Scala won't do this
println(bToC(aToB(toA(5))).total)
println(bToC(aToB(new A(5))).total)
// Just this
println(bToC(new B(5, 5)).total)
// No implicits required
println(new C(5, 5, 10).total)
}
object T2Translated {
implicit def toA(n: Int): A = new A(n)
implicit def aToB[A1 <% A](a: A1): B = new B(a.n, a.n)
implicit def bToC[B1 <% B](b: B1): C = new C(b.m, b.n, b.m + b.n)
// Scala does this
println(bToC(5)(x => aToB(x)(y => toA(y))).total)
println(bToC(new A(5))(x => aToB(x)(identity)).total)
println(bToC(new B(5, 5))(identity).total)
// no implicits required
println(new C(5, 5, 10).total)
}
では、一方
bToC
は暗黙の変換として使われています。
aToB
と
toA
として渡されます。
暗黙のパラメータ
として渡され、暗黙の変換として連結されるのではありません。
EDIT
気になる関連質問。
関連
-
[解決済み】Scalaのコンテキストとビューバウンドとは何ですか?
-
[解決済み】Scalaはどこでimplicitを探すのか?
-
[解決済み] Any、AnyVal、AnyRef、Objectの関係と、Javaコードでのマッピングについて教えてください。
-
[解決済み] ジッパーがコモナドである理由を理解する
-
[解決済み] Apache SparkでDataframeのカラム値をListとして抽出する。
-
[解決済み] sbtのヒープサイズを設定するには?
-
[解決済み] 上位互換型はどんなときに役立つのか?
-
[解決済み] Scalaのコレクションにenrich-my-libraryパターンを適用するにはどうしたらいいですか?
-
[解決済み] scalaのApp traitとmainメソッドの違いについて
-
[解決済み] Scala における => と () => の意味 [重複].
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】Scalaのコンテキストとビューバウンドとは何ですか?
-
[解決済み】Scalaはどこでimplicitを探すのか?
-
[解決済み] Scalaのパターンマッチはなぜ変数で機能しないのですか?
-
[解決済み] scalaは推論される型の「許容される複雑さ」にどのような制限を設けているのでしょうか?
-
[解決済み] sbtとGradleの比較 [終了しました]。
-
[解決済み] build.sbtとbuild.scalaの違いは何ですか?
-
[解決済み] Scalaでサブアレイを取得する正しい方法は何ですか?
-
[解決済み] scala で複数の case class をマッチングさせる
-
[解決済み] Scala型プログラミングリソース
-
[解決済み] Scalaのコレクションにenrich-my-libraryパターンを適用するにはどうしたらいいですか?