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.

Scalaで型クラス入門

5,130 views

Published on

社内勉強会で使った、Scalaを使って型クラスを理解するための説明スライド。

Published in: Technology
  • Professional bull rider Travis Rowe is convinced that the "Demolisher" Betting System is so good, it will eventually force the sportsbook to shut down his wagers to a minimum! ♣♣♣ http://t.cn/A6zP2wH9
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Follow the link, new dating source: ♥♥♥ http://bit.ly/2ZDZFYj ♥♥♥
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Sex in your area is here: ❶❶❶ http://bit.ly/2ZDZFYj ❶❶❶
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • accessibility Books Library allowing access to top content, including thousands of title from favorite author, plus the ability to read or download a huge selection of books for your pc or smartphone within minutes ,Download or read Ebooks here ... ......................................................................................................................... Download FULL PDF EBOOK here { http://bit.ly/2m6jJ5M }
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • accessibility Books Library allowing access to top content, including thousands of title from favorite author, plus the ability to read or download a huge selection of books for your pc or smartphone within minutes ,Download or read Ebooks here ... ......................................................................................................................... Download FULL PDF EBOOK here { http://bit.ly/2m6jJ5M }
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

Scalaで型クラス入門

  1. 1. Scalaで型クラス入門 AMoAd 福原真 2015-11-06 Adtech Scala Meetup (2015-12-20 外部公開用に改定)
  2. 2. 株式会社サイバーエージェント アドテクスタジオ AMoAd所属 福原 真 @fukuo33 -2011/08 (主にJava) SIer として 金融、物流、外食、通信 etc様々なプロジェクトに参加 2011/09- (C言語 + Scala) 某アドネットワークシステム サーバサイドエンジニア 2013/04- (Scala + Java) 株式会社AMoAd サーバサイドエンジニア 自己紹介
  3. 3. このスライドについて CyberAgent Adtech Studio内で定期的に開催して いる「Adtech Scala Meetup」向けのスライドで す。 * 対象 ScalaでHello worldが書ける人 型クラスについて全く知らない人 関数型とか分かんないけど、手っ取り早く型クラスを何か理解し たい人
  4. 4. このスライドについて * 概要 まずHaskellベースで型クラスとは何かを説明します。 次にScalaでその型クラスをどう実現するのか説明し ます。 なるべく初心者向けに簡単に説明する所存です!
  5. 5. このスライドについて * 話すこと 型 型クラス アドホック多相 * 話さないこと 型引数 型コンストラクタ Kind Monoid Functor Applicative Monad
  6. 6. 前置き
  7. 7. 型とは? 一旦、オブジェクト指向のクラスを忘れて、型について思い出しましょう。 ※ 用語: 型 と データ型 は同意 int i = 123; char c = 'a'; C言語 Java int i = 123; boolean b = true; // String s = "abc" // String is Class, not data type. Haskell Prelude> :t True True :: Bool 赤枠が"型"です。※クラスではありません。
  8. 8. 型における値の範囲 型には取りうる値の範囲が決まっています。 Java int: -2147483648 .. 2147483647 boolean: true | false Haskell Prelude> :i Int data Int = GHC.Types.I# GHC.Prim.Int# Prelude> :i Bool data Bool = False | True
  9. 9. 型における値の範囲 Haskellではデータ型を自分で定義できます (JavaのEnumっぽい?) Haskell Prelude> data TrafficLight = Red | Yellow | Green Prelude> :t Red Red :: TrafficLight ※ RedはTrafficLight型の "値" です。
  10. 10. 型クラスとは?
  11. 11. 型クラスとは? 型クラスは、何らかの振る舞いを定義するインターフェースです。 ある型クラスのインスタンスである型は、その型クラスが記述する振 る舞いを実装します。 by 「すごいHaskellたのしく学ぼう!」 * 「型クラスはインターフェースを定義してる」とは? * 「型クラスのインスタンスである型」とは?
  12. 12. 「型クラスのインスタンスである型」とは? Prelude> 123 == 123 True Prelude> 'a' == 'b' False Prelude> :t (==) (==) :: Eq a => a -> a -> Bool Eq は型クラスです。 a は型です。 Eq a => はa型はEq型クラスのインスタンスである必要がある制約です。 (==)関数は、引数にEq型クラスのインスタンスa型を2つとり、Bool型を返し ます。 Javaのinterfaceに似てるかも? Haskell
  13. 13. 「型クラスのインスタンスである型」とは? Prelude> :i Int data Int = GHC.Types.I# GHC.Prim.Int# -- Defined in ‘GHC.Types’ .. instance Eq Int -- Defined in ‘GHC.Classes’ .. Prelude> :i Char data Char = GHC.Types.C# GHC.Prim.Char# -- Defined in ‘GHC.Types’ .. instance Eq Char -- Defined in ‘GHC.Classes’ .. Int型も、Char型も、Eq型クラスのインスタンスで す。
  14. 14. 「型クラスはインターフェースを定義してる」とは? Prelude> :i Eq class Eq a where (==) :: a -> a -> Bool (/=) :: a -> a -> Bool x == y = not(x/=y) x /= y = not(x==y) == 関数 と /= 関数が実装すべき関数(インターフェース)です。 ※ Eq型クラスはデフォルト実装が定義されているので、 (==) を実装すれば最小完全定義を満たせる
  15. 15. 「型クラスはインターフェースを定義してる」とは? Prelude> :i TrafficLight data TrafficLight = Red | Yellow | Green Prelude> Red == Red No instance for (Eq TrafficLight) arising from a use of ‘==’ Prelude> :set +m Prelude> instance Eq TrafficLight where Prelude| Red == Red = True Prelude| Green == Green = True Prelude| Yellow == Yellow = True Prelude| _ == _ = False Prelude| Prelude> :i TrafficLight data TrafficLight = Red | Yellow | Green instance Eq TrafficLight Prelude> Red == Red True 自分で定義した型をEq型クラスのインスタンスにしてみる ↑この時点では (==) は使えない ←Eq型クラスのインスタンスにしたので (==) が使えるようになった!
  16. 16. オブジェクト志向のクラスと何が違うのか? オブジェクト指向言語(Java, Python, C++)でクラスといえば、何 らかの動作をするオブジェクトを作るための青写真のことです。 でも、Haskellのクラスは、データを作る道具ではありません。 そうではなく、まずデータ型を作り、それから「このデータには何がで きるんだろう?」と考えるのです。 by 「すごいHaskellたのしく学ぼう!」 つまりdata型宣言時に"特徴"を与えるのではなく アドホック(場当たり的)に型クラスのインスタンスであることを宣言する。 型クラスはアドホック多相(adhoc polymorphism)を実現していると言えます。
  17. 17. 型クラスとは? 型クラスについて聞かれたら「あーアドホック多相 のことねー」と言っとけばなんとかなります!(多 分) ここからはアドホック多相をScalaでどう実現する のかを説明します!
  18. 18. 多相 (Polymorphis m)とは?
  19. 19. 多相(Polymorphism)とは? ポリモーフィズムあるいはポリモルフィズム(Polymorphism)と は、プログラミング言語の型システムの性質を表すもので、プログ ラミング言語の各要素(定数、変数、式、オブジェクト、関数、メ ソッドなど)についてそれらが複数の型に属することを許すという 性質を指す。 by Wikipedia アドホック多相にいく前に、多相覚えてますか?
  20. 20. 多相(Polymorphism)とは? 普段、オブジェクト指向言語で使ってるのは 派生型多相(Subtype Polymorphism) abstract class Animal { def bark(): String } class Cat extends Animal { def bark() = "にゃあ" } class Dog extends Animal { def bark() = "わん" } val animal1 = new Cat() val animal2 = new Dog() animal1.bark // "にゃあ" animal2.bark // "わん" Scala
  21. 21. 多相(Polymorphism)とは? 型パラメータを使うのは パラメトリック多相(Parametric Polymorphism) JavaではGenericsって呼ばれますね。 scala> def concat[A](l1: List[A], l2: List[A]) = l1 ++ l2 concat: [A](l1: List[A], l2: List[A])List[A] scala> concat(List(1, 2, 3), List(4, 5, 6)) res0: List[Int] = List(1, 2, 3, 4, 5, 6) scala> concat(List("aa", "bb", "cc"), List("dd", "ee", "ff")) res1: List[String] = List(aa, bb, cc, dd, ee, ff) Scala
  22. 22. 多相(Polymorphism)とは? オーバーロードはポリモーフィズムの一種 ※自信なしです。各自調べてください class Clazz { def foo() = "foo" def foo(b: Boolean) = s"foo: $b" def foo(s: String) = s"foo: $s" } val c = new Clazz() c.foo() // "foo" c.foo(true) // "foo: true" c.foo("huga") // "foo: huga" Scala
  23. 23. Scalaで アドホック多 相を実現する には?
  24. 24. Implicits Implicit (暗黙の∼∼)は、Scalaで型クラスを実現する ために導入されたらしい Poor Man's Type Classs Martin Odersky http://lampwww.epfl.ch/~odersky/talks/wg2.8- boston06.pdf
  25. 25. implicit conversion 暗黙の型変換を使って、アドホックに多相を実現する scala> c.foo(123) <console>:13: error: overloaded method value foo with alternatives: (s: String)String <and> (b: Boolean)String cannot be applied to (Int) c.foo(123) ^ scala> implicit def intToString(i: Int): String = i.toString warning: there was one feature warning; re-run with -feature for details intToString: (i: Int)String scala> c.foo(123) res8: String = foo: 123 Scala P22の続き ↑この時点ではClazz#foo(Int)は使えない ←暗黙の型変換を定義することによって、 Clazz#foo(Int)が使えるようになった!
  26. 26. implicit parameter package sample.typeclass
 
 trait Plus[A] {
 def plus(a1: A, a2: A): A
 } 暗黙のパラメータを使って、アドホックに多相を実現する package sample
 
 import sample.typeclass.Plus
 
 package object implicits {
 implicit object IntPlus extends Plus[Int] {
 def plus(a1: Int, a2: Int) = a1 + a2
 }
 implicit object StringPlus extends Plus[String] {
 def plus(a1: String, a2: String) = a1 + a2
 }
 } package sample
 
 import sample.typeclass.Plus
 
 package object implicits2 {
 implicit object IntPlus extends Plus[Int] {
 def plus(a1: Int, a2: Int) = (a1 + a2) + (a1 + a2)
 }
 implicit object StringPlus extends Plus[String] {
 def plus(a1: String, a2: String) = (a1 + a2) + (a1 + a2)
 }
 } sample/typeclass/Plus.scala sample/implicits/package.scala sample/implicits2/package.scala Haskellの例(P12)と比較すると Plus[A] は型クラス。 IntPlus, StringPlus は型。 implicit object IntPlus extends Plus[Int] は、IntPlusは Plus[A]型クラスのインスタンス。
  27. 27. implicit parameter scala> import sample.typeclass.Plus import sample.typeclass.Plus scala> def plus[A: Plus](a1: A, a2: A)(implicit a: Plus[A]): A = a.plus(a1, a2) plus: [A](a1: A, a2: A)(implicit evidence$1: sample.typeclass.Plus[A], implicit a: sample.typeclass.Plus[A])A scala> plus(123, 200) <console>:10: error: could not find implicit value for evidence parameter of type sample.typeclass.Plus[Int] plus(123, 200) ^ scala> import sample.implicits._ import sample.implicits._ scala> plus(123, 200) res1: Int = 323 ↓この時点では plus は使えない ← 型クラスインスタンスが定義されたパッケージを importすることによって、plus()が使えるようになった!
  28. 28. implicit parameter scala> import sample.implicits2._ import sample.implicits2._ scala> plus(123, 200) res2: Int = 646 ↑ Scalaではimportを切り替えることに よって、実装が切り替えられる!
  29. 29. Scalaでアドホック多相を使う嬉しさ よく言う話としては、ライブラリで定義されたfinal classをアドホック 多相にて拡張することができる。 サブタイプ多相のみでも解決できることは多いと思いますが、継承関係 には手を加えずテスト時のみ動作を変えるとか利点があると思います。 ※ あとは各自調べて(汗) 開放/閉鎖原則(かいほうへいさげんそく。open/closed principle、OCP) とは、オブジェクト指向プログラミングにおいて、クラス(およびその他のプ ログラム単位)は 拡張に対して開いて (open) いなければならず、 修正に対して閉じて (closed) いなければならない という設計上の原則である。 by Wikipedia
  30. 30. 参考 主要な型クラスの紹介 @gakuzzz https://gist.github.com/gakuzzzz/8d497609012863b3ea50 怖くない型クラス @kmizu http://www.slideshare.net/kmizushima/ss-28707326 Scala の implicit parameter は型クラスの一種とはどういうことなのか @nkgt_chkonk http://nekogata.hatenablog.com/entry/2014/06/30/062342

×