View Bound/Context Bound

Scalaの「View Bound」と「Context Bound」について、そんなに解説がないわりに頻出するので、簡単な例をかいてみました。

Scala@東北とかでも結構当たり前のように登場する言葉・文法で、いまさら聞けない系の話題になってる感もある(全然そんなことないのですが)ので、参加者の中で耳にすると心が折れてしまう方がいれば参考にしてみてください。

View BoundContext Bound はいずれも、

「頻出する暗黙(implicit)変換・パラメータの利用方法」の
シンタックスシュガー


です。なので、理論的にステージが高い代物ではないので、REPLなどで動かして確認すればすぐ理解できると思います。

まずは、implicitのおさらいから

//implicitパラメータとは。。

implicit val a:Int = 1
implicit val s:String = "a"

def some(implicit v:Int) : Int = v
some // => 1

def some[Int](implicit v:Int) : Int = v
def some[String](implicit v:String) : String = v
some[Int] // => 1
some[String] // => "a"

//implicit パラメータに関数を入れる。

implicit def intBigger(a:Int,b:Int):Int = Math.max(a,b)
implicit def strBigger(a:String,b:String):String = if( a.compareTo(b) > 0 ) a else b

//普通に呼び出せば使えるが、

intBigger(1,2)
strBigger("a","b")

//これらをジェネリクスを使って抽象化すると、

def chooseBigger[T](a:T,b:T)(implicit func:(T,T)=>T) : T = func(a,b)

//(T,T)=>T 型の関数funcを探して採ってきてくれる。

chooseBigger(1,2) // => 2
chooseBigger("a","b") // => b
chooseBigger(1L,2L) // => (Long,Long)=>Long が定義していないためNotFoundエラー

ここまで理解できれば、View Bound / Context Bound は、そんなに難しくないです。

view bound とは

 def f1[T](implicit f2: T => A[T]) は、

 def f1[T <% A[T]] と書ける

このシンタックスシュガーが、View Boundと呼ばれている機能。

例)

trait Comparable[T]{
  def bigger(b:T):T
}
implicit def intComparable( a:Int ) = new Comparable[Int]{
  def bigger(b:Int):Int = Math.max(a,b)
}
implicit def stringComparable( a:String ) = new Comparable[String]{
  def bigger(b:String):String = if( a.compareTo(b) > 0 ) a else b
}

//ここでimplicit conversionは効いているので、

1.bigger(4)
"z".bigger("a")

//などとできますが、これらの暗黙変換を内部で利用する関数は、次のように書けて、

def chooseBigger2[T](a:T,b:T)(implicit comp: T => Comparable[T] ) : T = a.bigger(b)

chooseBigger2(1,2) // => 2
chooseBigger2("a","b") // => b

//chooseBigger2 のシンタックスシュガーとして以下のように書ける。
//(コンパイラがchooseBigger2の形に展開してくれる)

def chooseBigger3[T <% Comparable[T]](a:T,b:T) : T = a.bigger(b)
chooseBigger3(1,2)
chooseBigger3("a","b")


context bound とは

 def f[T]( implicit a:A[T] )

 def f[T:A] と書ける

このシンタックスシュガーが、Context Bound。
※Scala2.8からの導入です。

例)

//ここでは、単純に2つの引数を比較する比較メソッドを考える。
trait Comparator[T] {
  def bigger(a:T,b:T):T
}
implicit object IntComparator extends Comparator[Int]{
  def bigger(a:Int, b:Int):Int = Math.max(a,b)
}
implicit object StringComparator extends Comparator[String]{
  def bigger(a:String, b:String):String = if( a.compareTo(b) > 0 ) a else b
}

def chooseBigger4[T](a:T,b:T)( implicit comp:Comparator[T] ):T = comp.bigger(a,b)

chooseBigger4(1,2)
chooseBigger4("a","b")

//chooseBigger4は次のようにも書ける。

def chooseBigger5[T:Comparator](a:T,b:T):T = implicitly[Comparator[T]].bigger(a,b)

chooseBigger5(1,2)
chooseBigger5("a","b")

//chooseBigger4では、参照compを利用できましたが、
//chooseBigger5では(コード上では)参照が消えてしまうので、使いたいときは、
//implicitly[A[T]]で参照を取得できます。

同じカテゴリのエントリ
1.Lift再入門 / 8.javascriptからsubmitできない / 7.Ajax Form / 6.Radio、Checkboxについて / 5.行列型の編集FORM / 4.サーバーサイドバリデーションとサーバサイド関数 / 3.ログインFORM - S.param使ったら負け / 2.Snippetメソッドとして許される型 / sbt0.12.xで依存jar抽出タスク / scala2.10+lift2.5+NetBeans7.2 / Scalaで入門関数プログラミング / reactive-webを試してみました / Lift2.2M1のテンプレート機能 / Scala Compiler Plugin / View Bound/Context Bound / ScalaZa01参加してきました / Akka Frameworkチュートリアルの次 / Akka Frameworkチュートリアルその2 / Akka Frameworkチュートリアル / LiftでJCaptcha / Url Rewrite Filter / sbt-android-plugin / Android SDK for Scala / 祝Lift2.0リリース / Liftの携帯対応まとめ / Scala2.8への移行 / Lift 2.0-scala280-SNAPSHOT/sbt0.7.1 / Scalaお絵かき環境 - Kojo / Lift+Quartzでバッチ / Scala&Liftを採用した理由 / Liftでdate_select系ヘルパーを作る / LiftでAjax / LiftのSubmitかしこい / lift-mapperのpaginateを使う / snippetをspecする / Lift Mapperを拡張する / LiftのDBをMySQLに / Liftプロジェクト環境を整える / Scala本読み比べてみました / NetBeans6.7&scala / じつはScalaはライトな言語 / Scalaバザ~ル / lift1.0所感 / specsを読む / implicit def / ScalaならNetBeansがサイコー / scala勉強会@東北がスタート / それでも俺はLiftをやるってのか / Scala&Liftセットアップ / ブログリニューアル /
コメント
匿名さん
2010/10/15
「いいね!」ボタンがあったら押してますよ。
ありがとうございます。

コメントしてください

closed.