Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Implicit Explicit Scala       水島 宏太       (@kmizu)
自己紹介
の前にお約束
JIT(Just In Tsukkomi)歓迎
@kmizu http://twitter.com/kmizu    @ktmizushima (English)  http://twitter.com/ktmizushima          id:kmizushimahttp://d.h...
Continuation Workshop 2011 (2011/09/24)限定継続の人(Tiark Rompf)が来てた       あ、ありのまま(ry
ちなみにこの自己紹介は(ry
今回説明すること
その前にQuiz * 3
ルール:-Xprint:typer禁止
Q.1 A1-A3, B1-B3 を埋めてくださいval m = Map("A" -> 1, "B" -> 2)m.map{case (x, y) => (y, x)}m.map{case (x, y) => x}m.map[A1, A2]({...
A.1val m = Map("A" -> 1, "B" -> 2)m.map{case (x, y) => (y, x)}m.map{case (x, y) => x}m.map[(Int, String), Map[Int, String]...
Why ?
Q.2 A1, A2, B1, B2 を埋めてくださいval l1 = List(1, 2, 3)val l2 = List(1.5, 2.5, 3.5)l1.suml2.suml1.sum[A1](?:A2)l2.sum[B2](?:B2)
A.2val l1 = List(1, 2, 3)val l2 = List(1.5, 2.5, 3.5)l1.suml2.suml1.sum[Int](?:Numeric[Int])l2.sum[Double](?:Numeric[Doubl...
Why ?
Q.3 A1-A3, B1-B3 を埋めてくださいval l1 = List("A" -> 1, "B" -> 2)val l2 = List(1, 2, 3)l1.toMapl2.toMapl1.toMap[A1, A2](?:A3)l2.t...
A.3val l1 = List("A" -> 1, "B" -> 2)val l2 = List(1, 2, 3)l1.toMapl2.toMapl1.toMap[String, Int](?: (String, Int) <:< (Stri...
Why ?
3つに共通するもの
それは
Implicit Parameter
Implicit Parameter
最も誤解されてきた機能
実はとても強力な機能
implicit parameter=省略可能引数
とりあえず
implicit parameter
が今回のメイン
A.1~A.3の意味がわかる   ようになる(はず)
基本
def hoge(implicit x: Int) = x + 3implicit val INT: Int = 3println(hoge) → println(hoge(INT)) → 6
間違いではないが
全然嬉しくない
基本
trait Addible[A] {  def plus(x: A, y: A): A  def zero: A}implicit object IntAddible extends Addible[Int] {  def plus(x: In...
implicit宣言された型に適合する  implicitな値を拾ってくれる
implicit探索規則
基本:静的スコープで決まる
メソッド呼び出し時に「直接参 照可能な」implicitな値が対象
「直接参照可能な」の意味1. 同一スコープにimplicitな値が定義されている2. importによってimplicitな値が導入されている
例外規則
implicit parameterの型に「関連付けられ  たクラス/トレイト」のコンパニオンオ           ブジェクトも探索対象
「関連付けられたクラス/トレイト」
trait G[A, B, C] の場合:G, A, B, C のコンパニオンオブジェクトを探索
trait Addible[A] {  def plus(x: A, y: A): A  def zero: A}object Addible { //companion object  implicit object IntAddible e...
デフォルトで探索対象にして欲しいimplicitな値をコンパニオンオブジェクト           に入れると便利
何が嬉しい?
Doubleもsumしたくなった
implicit object DoubleAddible extends Addible[Int] {  def plus(x: Double, y: Double): Double = x + y  def zero: Double = 0...
元のデータ型に変更を加えずに
データ型の性質を新しく定義
特殊:implicit推論規則
implicitな値から型パラメータを      「逆向きに」推論可能
Scala 2.8で導入
implicit val tupleA: (Int, String) = (1, "A")implicit val tupleB: (Double, String) = (1.5, "B")def useImplicitTuple2[A, B]...
Aに応じて推論されるBが変わる
2.8コレクションには不可欠
A.1 ~ A.3の定義をもう一度見てみる
A.1val m = Map("A" -> 1, "B" -> 2)// def map [B, That] (f: ((A, B)) ⇒ B)(implicit bf: CanBuildFrom[Map[A, B], B, That]): T...
引数の型情報から順方向に推論 したのではThatはわからないimplicit推論規則による解決
scala.collection.immutable.Map のコンパニオンオブジェクト
package scala.collectionpackage immutableobject Map ... {  ..  //Coll = Map[_, _]  implicit def canBuildFrom[A, B]:     Ca...
(1) 任意の型A, B について CanBuildFrom[Map[_, _], (A, B), Map[A, B]]型のimplicitな値を生成可能
scala.collection.Iterableのコンパニオンオブジェクト
package scala.collection...object Iterable ... {  ..  //Coll = Iterable[A]  implicit def canBuildFrom[A]:     CanBuildFrom...
(2) 任意の型A, B について CanBuildFrom[Iterable[_, _], (A), Iterable[A]]型のimplicitな値を生成可能
適用優先度: (1) > (2)
(1)が適合していなくても   (2)が適合すればOK
A.2val l1 = List(1, 2, 3)val l2 = List(1.5, 2.5, 3.5)l1.suml2.sum// def sum [B >: A] (implicit num: Numeric[B]): Bl1.sum[I...
package scala.math...object Numeric {  trait IntIsIntegral extends Integral[Int] {     def plus(x: Int, y: Int): Int = x +...
A.3val l1 = List("A" -> 1, "B" -> 2)val l2 = List(1, 2, 3)l1.toMapl2.toMap                          名状し難い型l1.toMap[String,...
答えはPredefの中に
package scala.math...object Predef ... {  @implicitNotFound(msg = "Cannot prove that ${From} <:< ${To}.")  sealed abstract...
ポイント
sealed abstract class <:<[-From, +To]implicit def conforms[A]: A <:< A = singleton_<:<.asInstanceOf[A <:< A]
任意の型AについてA <: A 型のimplicitな値を生成    可能(多相的なimplicit)
名状し難い <:< の左辺:contravariant (-) 右辺: covariant(+)
def fun[A, B](a: A, b: B)(implicit ev: A <:< B)
A = Int, B = Any       つまり A <: B のとき(Int <:< Any) なimplicitな値が必要
(Int <:< Int) <: (Int <:< Any) なので      (<:< の右辺はcovariant)conforms[Int]: Int <: Int で適合する
A = Any, B = Int      つまり A <: B のとき(Any <:< Int) なimplicitな値が必要
(Any <:< Any) <: (Any <: Int) かつ    (Int <:< Int) <: (Any <: Int)   (<:< の左辺はcontravariant)       →コンパイルエラー
implicit parameterを使ったライブラリ/フレームワーク
Scala標準ライブラリ      Scalaz       sjson    ScalaCheck       spray       Akka      Squeryl         ...
たくさんある
implicit parameterを活用してみてください
通称コップ本 第二版 好評発売中Scala 2.8対応+付録Scala 2.9記事(by @kmizu)
宣伝(2)
こんなキーワードにピンと来たら(ry Cakeパターン, CONCEPTパターン, 限定継続 現場でのScala, Javaとの連携
Upcoming SlideShare
Loading in …5
×

Implicit Explicit Scala

3,919 views

Published on

Scalaのimplicit parameter入門的な何かです。

Published in: Technology
  • Sex in your area is here: ❤❤❤ http://bit.ly/2u6xbL5 ❤❤❤
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Follow the link, new dating source: ❤❤❤ http://bit.ly/2u6xbL5 ❤❤❤
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

Implicit Explicit Scala

  1. 1. Implicit Explicit Scala 水島 宏太 (@kmizu)
  2. 2. 自己紹介
  3. 3. の前にお約束
  4. 4. JIT(Just In Tsukkomi)歓迎
  5. 5. @kmizu http://twitter.com/kmizu @ktmizushima (English) http://twitter.com/ktmizushima id:kmizushimahttp://d.hatena.ne.jp/kmizushima Scala辻斬り ヒーラー
  6. 6. Continuation Workshop 2011 (2011/09/24)限定継続の人(Tiark Rompf)が来てた あ、ありのまま(ry
  7. 7. ちなみにこの自己紹介は(ry
  8. 8. 今回説明すること
  9. 9. その前にQuiz * 3
  10. 10. ルール:-Xprint:typer禁止
  11. 11. Q.1 A1-A3, B1-B3 を埋めてくださいval m = Map("A" -> 1, "B" -> 2)m.map{case (x, y) => (y, x)}m.map{case (x, y) => x}m.map[A1, A2]({case (x, y) => (y, x) })(?:A3)m.map[B1, B2]{case (x, y) => x })(?:B3)
  12. 12. A.1val m = Map("A" -> 1, "B" -> 2)m.map{case (x, y) => (y, x)}m.map{case (x, y) => x}m.map[(Int, String), Map[Int, String]]{ case (x, y) => (y, x) }(?:CanBuildFrom[Map[String, Int], String, Map[Int, String])m.map[String, Iterable[String]]({ case (x, y) => x })(?:CanBuildFrom[Map[String, Int], String, Iterable[String]]
  13. 13. Why ?
  14. 14. Q.2 A1, A2, B1, B2 を埋めてくださいval l1 = List(1, 2, 3)val l2 = List(1.5, 2.5, 3.5)l1.suml2.suml1.sum[A1](?:A2)l2.sum[B2](?:B2)
  15. 15. A.2val l1 = List(1, 2, 3)val l2 = List(1.5, 2.5, 3.5)l1.suml2.suml1.sum[Int](?:Numeric[Int])l2.sum[Double](?:Numeric[Double])
  16. 16. Why ?
  17. 17. Q.3 A1-A3, B1-B3 を埋めてくださいval l1 = List("A" -> 1, "B" -> 2)val l2 = List(1, 2, 3)l1.toMapl2.toMapl1.toMap[A1, A2](?:A3)l2.toMap[B1, B2](?:B3)
  18. 18. A.3val l1 = List("A" -> 1, "B" -> 2)val l2 = List(1, 2, 3)l1.toMapl2.toMapl1.toMap[String, Int](?: (String, Int) <:< (String, Int))l2.toMap[B1, B2](?:B3)→ error: Cannot prove that Int <:< (T, U).
  19. 19. Why ?
  20. 20. 3つに共通するもの
  21. 21. それは
  22. 22. Implicit Parameter
  23. 23. Implicit Parameter
  24. 24. 最も誤解されてきた機能
  25. 25. 実はとても強力な機能
  26. 26. implicit parameter=省略可能引数
  27. 27. とりあえず
  28. 28. implicit parameter
  29. 29. が今回のメイン
  30. 30. A.1~A.3の意味がわかる ようになる(はず)
  31. 31. 基本
  32. 32. def hoge(implicit x: Int) = x + 3implicit val INT: Int = 3println(hoge) → println(hoge(INT)) → 6
  33. 33. 間違いではないが
  34. 34. 全然嬉しくない
  35. 35. 基本
  36. 36. trait Addible[A] { def plus(x: A, y: A): A def zero: A}implicit object IntAddible extends Addible[Int] { def plus(x: Int, y: Int): Int = x + y def zero: Int = 0}def sum[A](nums: List[A])(implicit addible: Addible[A]): A = { nums.foldLeft(addible.zero)((x, y) => addible.plus(x, y))}println(sum(List(1, 2, 3, 4, 5)))→ println(sum(List(1, 2, 3, 4, 5))(IntAddible))
  37. 37. implicit宣言された型に適合する implicitな値を拾ってくれる
  38. 38. implicit探索規則
  39. 39. 基本:静的スコープで決まる
  40. 40. メソッド呼び出し時に「直接参 照可能な」implicitな値が対象
  41. 41. 「直接参照可能な」の意味1. 同一スコープにimplicitな値が定義されている2. importによってimplicitな値が導入されている
  42. 42. 例外規則
  43. 43. implicit parameterの型に「関連付けられ たクラス/トレイト」のコンパニオンオ ブジェクトも探索対象
  44. 44. 「関連付けられたクラス/トレイト」
  45. 45. trait G[A, B, C] の場合:G, A, B, C のコンパニオンオブジェクトを探索
  46. 46. trait Addible[A] { def plus(x: A, y: A): A def zero: A}object Addible { //companion object implicit object IntAddible extends Addible[Int] { def plus(x: Int, y: Int): Int = x + y def zero: Int = 0 }}def sum[A](nums: List[A])(implicit addible: Addible[A]): A = { nums.foldLeft(addible.zero)((x, y) => addible.plus(x, y))}println(sum(List(1, 2, 3, 4, 5)))→ println(sum(List(1, 2, 3, 4, 5))(IntAddible)) // OK
  47. 47. デフォルトで探索対象にして欲しいimplicitな値をコンパニオンオブジェクト に入れると便利
  48. 48. 何が嬉しい?
  49. 49. Doubleもsumしたくなった
  50. 50. implicit object DoubleAddible extends Addible[Int] { def plus(x: Double, y: Double): Double = x + y def zero: Double = 0.0}println(sum(List(1.0, 2.0, 3.0)))→ println(sum(List(1.0, 2.0, 3.0))(DoubleAddible))
  51. 51. 元のデータ型に変更を加えずに
  52. 52. データ型の性質を新しく定義
  53. 53. 特殊:implicit推論規則
  54. 54. implicitな値から型パラメータを 「逆向きに」推論可能
  55. 55. Scala 2.8で導入
  56. 56. implicit val tupleA: (Int, String) = (1, "A")implicit val tupleB: (Double, String) = (1.5, "B")def useImplicitTuple2[A, B](value: A)(implicit tuple: (A, B)): B = { tuple._2}println(useImplicitTuple2(100)) // Aprintln(useImplicitTuple2(1.5)) // B
  57. 57. Aに応じて推論されるBが変わる
  58. 58. 2.8コレクションには不可欠
  59. 59. A.1 ~ A.3の定義をもう一度見てみる
  60. 60. A.1val m = Map("A" -> 1, "B" -> 2)// def map [B, That] (f: ((A, B)) ⇒ B)(implicit bf: CanBuildFrom[Map[A, B], B, That]): Thatm.map{case (x, y) => (y, x)}m.map{case (x, y) => x}m.map[(Int, String), Map[Int, String]]{ case (x, y) => (y, x) }(?:CanBuildFrom[Map[String, Int], String, Map[Int, String])m.map[String, Iterable[String]]({ case (x, y) => x })(?:CanBuildFrom[Map[Int, String], String, Iterable[String]])
  61. 61. 引数の型情報から順方向に推論 したのではThatはわからないimplicit推論規則による解決
  62. 62. scala.collection.immutable.Map のコンパニオンオブジェクト
  63. 63. package scala.collectionpackage immutableobject Map ... { .. //Coll = Map[_, _] implicit def canBuildFrom[A, B]: CanBuildFrom[Coll, (A, B), Map[A, B]] = new MapCanBuildFrom[A, B]}
  64. 64. (1) 任意の型A, B について CanBuildFrom[Map[_, _], (A, B), Map[A, B]]型のimplicitな値を生成可能
  65. 65. scala.collection.Iterableのコンパニオンオブジェクト
  66. 66. package scala.collection...object Iterable ... { .. //Coll = Iterable[A] implicit def canBuildFrom[A]: CanBuildFrom[Coll, (A), Iterable[A]] = new GenericCanBuildFrom[A]}
  67. 67. (2) 任意の型A, B について CanBuildFrom[Iterable[_, _], (A), Iterable[A]]型のimplicitな値を生成可能
  68. 68. 適用優先度: (1) > (2)
  69. 69. (1)が適合していなくても (2)が適合すればOK
  70. 70. A.2val l1 = List(1, 2, 3)val l2 = List(1.5, 2.5, 3.5)l1.suml2.sum// def sum [B >: A] (implicit num: Numeric[B]): Bl1.sum[Int](?:Numeric[Int])l2.sum[Double](?:Numeric[Double])
  71. 71. package scala.math...object Numeric { trait IntIsIntegral extends Integral[Int] { def plus(x: Int, y: Int): Int = x + y def minus(x: Int, y: Int): Int = x - y def times(x: Int, y: Int): Int = x * y def quot(x: Int, y: Int): Int = x / y def rem(x: Int, y: Int): Int = x % y def negate(x: Int): Int = -x def fromInt(x: Int): Int = x def toInt(x: Int): Int = x.toInt def toLong(x: Int): Long = x def toFloat(x: Int): Float = x def toDouble(x: Int): Double = x } .. // Integeral[T] <: Numeric[T] なので、 Numeric[Int]のimplicitな値も同時に定義 // していることになる implicit object IntIsIntegral extends IntIsIntegral with Ordering.IntOrdering}
  72. 72. A.3val l1 = List("A" -> 1, "B" -> 2)val l2 = List(1, 2, 3)l1.toMapl2.toMap 名状し難い型l1.toMap[String, Int](?: (String, Int) <:< (String, Int))l2.toMap[B1, B2](?:B3)→ error: Cannot prove that Int <:< (T, U).
  73. 73. 答えはPredefの中に
  74. 74. package scala.math...object Predef ... { @implicitNotFound(msg = "Cannot prove that ${From} <:< ${To}.") sealed abstract class <:<[-From, +To] extends (From => To) with Serializable 名状し難い型の定義 private[this] final val singleton_<:< = new <:<[Any,Any] { def apply(x: Any): Any = x } // not in the <:< companion object because it is also // intended to subsume identity (which is no longer implicit) implicit def conforms[A]: A <:< A = singleton_<:<.asInstanceOf[A <:< A]}
  75. 75. ポイント
  76. 76. sealed abstract class <:<[-From, +To]implicit def conforms[A]: A <:< A = singleton_<:<.asInstanceOf[A <:< A]
  77. 77. 任意の型AについてA <: A 型のimplicitな値を生成 可能(多相的なimplicit)
  78. 78. 名状し難い <:< の左辺:contravariant (-) 右辺: covariant(+)
  79. 79. def fun[A, B](a: A, b: B)(implicit ev: A <:< B)
  80. 80. A = Int, B = Any つまり A <: B のとき(Int <:< Any) なimplicitな値が必要
  81. 81. (Int <:< Int) <: (Int <:< Any) なので (<:< の右辺はcovariant)conforms[Int]: Int <: Int で適合する
  82. 82. A = Any, B = Int つまり A <: B のとき(Any <:< Int) なimplicitな値が必要
  83. 83. (Any <:< Any) <: (Any <: Int) かつ (Int <:< Int) <: (Any <: Int) (<:< の左辺はcontravariant) →コンパイルエラー
  84. 84. implicit parameterを使ったライブラリ/フレームワーク
  85. 85. Scala標準ライブラリ Scalaz sjson ScalaCheck spray Akka Squeryl ...
  86. 86. たくさんある
  87. 87. implicit parameterを活用してみてください
  88. 88. 通称コップ本 第二版 好評発売中Scala 2.8対応+付録Scala 2.9記事(by @kmizu)
  89. 89. 宣伝(2)
  90. 90. こんなキーワードにピンと来たら(ry Cakeパターン, CONCEPTパターン, 限定継続 現場でのScala, Javaとの連携

×