[解決済み】Scalaのコンテキストとビューバウンドとは何ですか?
質問
コンテキストバウンズとビューバウンズとは何か、その違いは何か、わかりやすく教えてください。
わかりやすい例もあるといいですね。
どのように解決するのですか?
この質問はすでにされていると思ったのですが、もしそうなら、その質問は"related"のバーには表示されていません。そこで、ここに紹介します。
ビューバウンドとは何ですか?
A
ビューバウンド
は、Scala で導入されたメカニズムで、ある種の
A
あたかも
それは、ある種の
B
. 典型的な構文はこうです。
def f[A <% B](a: A) = a.bMethod
言い換えると
A
への暗黙の変換が必要です。
B
を呼び出すことができるようになります。
B
型のオブジェクトに対するメソッド
A
. 標準ライブラリにおけるビュー境界の最も一般的な使い方(Scala 2.8.0以前はとにかく)は
Ordered
のような、このような。
def f[A <% Ordered[A]](a: A, b: A) = if (a < b) a else b
を変換することができますので
A
を
Ordered[A]
であり、また
Ordered[A]
はメソッドを定義しています。
<(other: A): Boolean
という式が使えます。
a < b
.
ご注意ください ビューバウンドは非推奨です そのため、避けてください。
コンテキストバウンドとは何ですか?
コンテキストバウンズはScala 2.8.0で導入され、通常、いわゆる 型クラスパターン Haskellの型クラスが提供する機能を、より冗長な方法でエミュレートしたコードパターンである。
ビューバウンドは単純な型に使用できますが(例えば。
A <% String
) が、コンテキストバウンドでは
パラメータ化された型
のような
Ordered[A]
とは異なり
String
.
コンテキストバウンドは、暗黙の
値
の代わりに、ビューバウンドの暗黙の
変換
. これは、ある型に対して、次のように宣言するために使用されます。
A
という型の暗黙の値があります。
B[A]
が利用できます。構文は次のようになります。
def f[A : B](a: A) = g(a) // where g requires an implicit value of type B[A]
これは、ビューバウンドよりも使い方がすぐには分からないので、混乱する。Scalaでよくある使用例はこうだ。
def f[A : ClassManifest](n: Int) = new Array[A](n)
An
Array
パラメータ化された型の初期化には
ClassManifest
というのは、型の消去と配列の非消去の性質に関連した難解な理由があるからです。
ライブラリによくあるもう一つの例は、もう少し複雑です。
def f[A : Ordering](a: A, b: A) = implicitly[Ordering[A]].compare(a, b)
ここです。
implicitly
は、欲しい暗黙の値を取得するために使われます。
Ordering[A]
というメソッドを定義しているクラスです。
compare(a: A, b: A): Int
.
以下、別の方法について見ていきます。
View BoundsとContext Boundsはどのように実装されていますか?
ビュー境界とコンテキスト境界の両方が暗黙のパラメータで実装されていることは、その定義からして驚くには値しないでしょう。実は、私が示した構文は、実際に何が起こるかを示す構文上の糖分なのです。どのように糖分を取り除くかは、以下をご覧ください。
def f[A <% B](a: A) = a.bMethod
def f[A](a: A)(implicit ev: A => B) = a.bMethod
def g[A : B](a: A) = h(a)
def g[A](a: A)(implicit ev: B[A]) = h(a)
そのため、当然ながら完全な構文で書くことができ、特にコンテキスト・バウンディングに有効である。
def f[A](a: A, b: A)(implicit ord: Ordering[A]) = ord.compare(a, b)
ビューバウンドは何に使うのですか?
ビューバウンドは、主に次のような目的で使用されます。 pimp my library これは、既存のクラスにメソッドを追加するパターンですが、元の型を何らかの形で返したい場合に使用します。もし、その型を返す必要がないのであれば、ビューバウンドは必要ありません。
ビューバインドの典型的な使用例としては
Ordered
. ただし
Int
は
Ordered
例えば、暗黙のうちに変換が行われているにもかかわらず。先に示した例では、変換されない型を返しているので、ビューバインドが必要です。
def f[A <% Ordered[A]](a: A, b: A): A = if (a < b) a else b
この例は、ビューバウンドがないと動きません。しかし、もし別の型を返すのであれば、もうビューバウンドは必要ありません。
def f[A](a: Ordered[A], b: A): Boolean = a < b
ここでの変換は、(必要であれば)パラメータを
f
ということで
f
は知る必要がない。
そのほか
Ordered
このライブラリで最もよく使われるのは
String
と
Array
は,Scalaのコレクションと同じようにJavaのクラスである.例えば
def f[CC <% Traversable[_]](a: CC, b: CC): CC = if (a.size < b.size) a else b
これをビューバウンドなしで行おうとすると
String
は
WrappedString
(Scala 2.8)、同様に
Array
.
戻り値の型のパラメータとしてのみ使用する場合でも、同様のことが起こります。
def f[A <% Ordered[A]](xs: A*): Seq[A] = xs.toSeq.sorted
Context Boundsは何に使うのですか?
コンテキストバウンズは、主に以下のような用途で使用されます。 型クラスパターン Haskellの型クラスへの言及として。基本的にこのパターンは、暗黙のアダプターパターンのようなもので機能を利用できるようにすることで、継承に代わるものを実装しています。
典型的な例は、Scala 2.8 の
Ordering
を置き換えたものです。
Ordered
Scala のライブラリ全体に適用されます。使い方は
def f[A : Ordering](a: A, b: A) = if (implicitly[Ordering[A]].lt(a, b)) a else b
しかし、通常はこのように書かれているのを見かける。
def f[A](a: A, b: A)(implicit ord: Ordering[A]) = {
import ord.mkOrderingOps
if (a < b) a else b
}
の中のいくつかの暗黙の変換を利用する。
Ordering
で、伝統的な演算子スタイルを可能にします。Scala 2.8でのもう一つの例として
Numeric
:
def f[A : Numeric](a: A, b: A) = implicitly[Numeric[A]].plus(a, b)
より複雑な例として、新しいコレクションの使用法である
CanBuildFrom
しかし、それについてはすでに非常に長い回答があるので、ここでは避けます。また、前述したように
ClassManifest
これは具象型を持たない新しい配列を初期化するために必要です。
型クラスパターンによるコンテキストバウンドは、関心事の分離を可能にするため、自分のクラスで使われる可能性が高いが、ビューバウンドは良い設計によって自分のコードで回避できる(他人の設計を回避するために使われることがほとんどである)。
コンテキストバウンズは以前から可能でしたが、2010年に本格的に普及し、現在ではScalaの最も重要なライブラリやフレームワークのほとんどで、ある程度使用されています。ScalazライブラリはHaskellのパワーをScalaに取り入れたもので、その使い方の最も極端な例だ。 型クラスパターンを読んで、型クラスパターンの使い方にもっと詳しくなることをお勧めする。
EDIT
気になる関連質問
関連
-
[解決済み] Scalaでswitch/case(単純なパターンマッチ)を使うには?
-
[解決済み] Scalaの「コンテキストバウンド」とは何ですか?
-
[解決済み] Spark - Sparkでパーセンタイルを計算する方法は?
-
[解決済み] Scalaのオブジェクトとクラスの違い
-
[解決済み] Scalaのcase classとclassの違いは何ですか?
-
[解決済み] Scalaのapply関数とは何ですか?
-
[解決済み】Scalaにおける中括弧と括弧の正式な違い、また、どのような場合に使用すべきなのか?
-
[解決済み】Scalaのvarとvalの定義の違いは何ですか?
-
[解決済み】Scalaのyieldとは何ですか?
-
[解決済み] 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 underscore - ERROR: 展開された関数のパラメータ型が見つかりません。
-
[解決済み] スパークSPLラウンド&ブラウンド
-
[解決済み] GSON JsonObject "Unsupported Operation Exception: null" getAsString
-
[解決済み] Scalaの「コンテキストバウンド」とは何ですか?
-
[解決済み] NoClassDefFoundError: org/apache/hadoop/fs/StreamCapabilities (s3データをsparkで読み込む際に発生します。
-
[解決済み] scala.Float to java.Float k/v変換でScala MapをJava Mapに変換するにはどうしたらいいですか?
-
[解決済み】Scala 2.8 breakOut
-
[解決済み】良いスカラズの紹介【終了しました
-
[解決済み】Scalaのコンテキストとビューバウンドとは何ですか?
-
[解決済み】Scalaはどこでimplicitを探すのか?