Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Try Cats

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.
Avatar for fuzyco fuzyco
January 11, 2018

Try Cats

Scalaの関数型ライブラリCatsをやってみた話です。

Avatar for fuzyco

fuzyco

January 11, 2018
Tweet

More Decks by fuzyco

Other Decks in Technology

Transcript

  1. $BUTWT4DBMB[ $BUT ɾ৽͍͠σʔλܕ ɾ࣮༻্ඞཁͳશͯͷ൚༻ؔ਺ͷ࣮૷  ΞυϗοΫଟ૬ੑɺUSBJU JNQMJDJU ೣ൪ΑΓҾ༻ 4DBMB[ ɾ৽͍͠σʔλܕ

    ɾඪ४Ϋϥεͷ֦ு 0QUJPO0QT -JTU0QT  ɾ࣮༻্ඞཁͳશͯͷ൚༻ؔ਺ͷ࣮૷  ΞυϗοΫଟ૬ੑɺUSBJU JNQMJDJU ಠश4DBMB[ΑΓҾ༻
  2. &WBMϞφυ ධՁΛ੍ޚ͢Δσʔλܕ import cats.Eval // valͷΑ͏ʹఆٛ࣌ʹධՁ val x = Eval.now

    { println("Computing X") math.random } // Computing X // x: cats.Eval[Double] = Now(0.8724950064732552) // defͷΑ͏ʹৗʹධՁ val y = Eval.always { println("Computing Y") math.random } // y: cats.Eval[Double] = cats.Always@5212e1f5 // lazy valͷΑ͏ʹ஗ԆධՁ val z = Eval.later { println("Computing Z") math.random } // z: cats.Eval[Double] = cats.Later@33eda11
  3. &WBMϞφυ ධՁΛ੍ޚ͢Δσʔλܕ x.value // first access // res9: Double =

    0.8724950064732552 x.value // second access // res10: Double = 0.8724950064732552 y.value // first access // Computing Y // res11: Double = 0.8795680260041828 y.value // second access // Computing Y // res12: Double = 0.5640213059400854 z.value // first access // Computing Z // res13: Double = 0.5813583535421343 z.value // second access // res14: Double = 0.5813583535421343 import cats.Eval // valͷΑ͏ʹఆٛ࣌ʹධՁ val x = Eval.now { println("Computing X") math.random } // Computing X // x: cats.Eval[Double] = Now(0.8724950064732552) // defͷΑ͏ʹৗʹධՁ val y = Eval.always { println("Computing Y") math.random } // y: cats.Eval[Double] = cats.Always@5212e1f5 // lazy valͷΑ͏ʹ஗ԆධՁ val z = Eval.later { println("Computing Z") math.random } // z: cats.Eval[Double] = cats.Later@33eda11
  4. &WBMʹΑΔ࠶ؼॲཧ def factorial(n: BigInt): BigInt = if(n == 1) n

    else n * factorial(n - 1) factorial(50000) // ࣮ߦ ຤ඌ࠶ؼͰͳ͍࠶ؼؔ਺
  5. &WBMʹΑΔ࠶ؼॲཧ def factorial(n: BigInt): BigInt = if(n == 1) n

    else n * factorial(n - 1) factorial(50000) // ࣮ߦ ຤ඌ࠶ؼͰͳ͍࠶ؼؔ਺ ελοΫΦʔόʔϑϩʔ͕ى͖Δ factorial(50000) // java.lang.StackOverflowError // ...
  6. &WBMʹΑΔ࠶ؼॲཧ def factorial(n: BigInt): Eval[BigInt] = if(n == 1) {

    Eval.now(n) } else { factorial(n - 1).map(_ * n) } factorial(50000).value // ࣮ߦ &WBMΛ༻͍ͨίʔυʹมߋ
  7. &WBMʹΑΔ࠶ؼॲཧ def factorial(n: BigInt): Eval[BigInt] = if(n == 1) {

    Eval.now(n) } else { factorial(n - 1).map(_ * n) } factorial(50000).value // ࣮ߦ &WBMΛ༻͍ͨίʔυʹมߋ factorial(50000).value // java.lang.StackOverflowError // ... ελοΫΦʔόʔϑϩʔ͕ى͖Δ
  8. &WBMʹΑΔ࠶ؼॲཧ def factorial(n: BigInt): Eval[BigInt] = if(n == 1) {

    Eval.now(n) } else { Eval.defer(factorial(n - 1).map(_ * n)) } factorial(50000).value // ࣮ߦ // res20: BigInt = //33473205095971448369154760940714864779127732…… &WBMEFGFSϝιουΛ࢖ͬͯ͞ΒʹϦϑΝΫλϦϯά
  9. &WBMʹΑΔ࠶ؼॲཧ def factorial(n: BigInt): Eval[BigInt] = if(n == 1) {

    Eval.now(n) } else { Eval.defer(factorial(n - 1).map(_ * n)) } factorial(50000).value // ࣮ߦ // res20: BigInt = //33473205095971448369154760940714864779127732…… factorial(50000).value // res20: BigInt = //33473205095971448369154760940714864779127732…… &WBMEFGFSϝιουΛ࢖ͬͯ͞ΒʹϦϑΝΫλϦϯά ਖ਼ৗऴྃ
  10. &WBMʹΑΔ࠶ؼॲཧ &WBMEFGFSϝιου͸ԿΛ͍ͯ͠Δͷ͔ʁ def defer[A](a: => Eval[A]): Eval[A] = new Eval.Defer[A](a

    _) {} sealed abstract class Defer[A](val thunk: () => Eval[A]) extends Eval[A] { def memoize: Eval[A] = Memoize(this) def value: A = evaluate(this) } &WBM<">Λฦ͢ܭࢉΛ஗Ԇ͍ͯ͠Δ τϥϯϙϦϯԽ͕ߦΘΕɺؔ਺͕਺चͭͳ͗ Ͱݺ͹Εͳ͘ͳΔ
  11. 'VODUPS -JTU 0QUJPOͳͲʹରͯ͠ɺ แ·Εͨ஋ʹରͯ͠Ҿ਺ؔ਺Λద༻͢ΔॲཧΛఏڙ͢ΔܕΫϥε List(1, 2, 3).map(_ * 2) //

    List(2, 4, 6) Some(1).map(_ * 2) // Some(2) @typeclass trait Functor[F[_]] extends functor.Invariant[F] { self => def map[A, B](fa: F[A])(f: A => B): F[B] .... }
  12. "QQMZ 'VODUPSΛ֦ுͯ͠ɺ/ݸͷ'VODUPS஋ʹ/Ҿ਺ؔ਺Λ ద༻͢ΔॲཧΛఏڙ͢ΔܕΫϥε import cats.implicits._ // implicit defͰ҉໧తʹmap2, map3͕ద༻͞ΕΔ (Some(1),

    Some(2)).mapN(_ + ) // Some(3) (Some(1), Some(2), Some(3)).mapN(_ * _ * _) // Some(6) (List("ha", "heh", "hmm"), List("?", "!", ".")) mapN {_ + _} // List(ha?, ha!, ha., heh?, heh!, heh., hmm?, hmm!, hmm.)
  13. "QQMJDBUJWF'VODUPS "QQMJDBUJWF͸"QQMZʹ QVSFϝιου "'<"> Λ௥Ճ͍ͯ͠ΔܕΫϥε ϓϦϛςΟϒ஋Λ"QQMJDBUJWFܕʹม׵ͯ͠ɺ ଞͷ"QQMJDBUJWFͱ߹੒Ͱ͖Δɹ DBUTͷ7BMJEBUFE͸BQQMJDBUJWFGVODUPSΛܗ੒͢Δ 1.pure[Option] //

    Some(1) // શͯͷΠϕϯτΛݕূ্ͨ͠Ͱɺ߹੒Λߦ͏ val result = (valid[String, String]("event 1 ok") |@| invalid[String, String]("event 2 failed!") |@| invalid[String, String]("event 3 failed!")) map {_ + _ + _} // result: cats.data.Validated[String,String] = Invalid(event 2 failed!event 3 failed!) DPNQPTF G QVSF G DPNQPTF QVSF G G QVSF͸ಉҰ཯Λຬͨ͢
  14. .POBE "QQMJDBUJWF'VODUPS͸ෳ਺ͷ'VODUPS஋Λѻ͏͜ͱ͕Ͱ͖͕ͨɺ લͷ'VODUPS஋ʹґଘ͢ΔॲཧΛॻ͚ͳ͍ɻ def hogeOption(a: Int): Option[Int] = Some(a) hogeOption(1).flatMap(a

    => hogeOption(a).map(b => a+b)) // Some(2) for { a <- hogeOption(1) b <- hogeOption(a) } yield (a + b) // Some(2) .POBE͸લͷ஋ʹґଘ͢ΔॲཧΛఏڙ͢ΔܕΫϥε /POFqBU.BQ G qBU.BQ H /POFqBU.BQ BG B qBU.BQ H qBU.BQ͸݁߹཯Λຬͨ͢
  15. Ϟφυ·ͱΊ Ϟφυͱ͸ɺ݁߹཯ͱಉҰ཯Λຬͨ͢࠷খݶͷ ϞφυίϯϏωʔλͷू·Γͷ͍ͣΕ͔Λ࣮૷ͨ͠΋ͷͰ͋Δɻ DPNQPTF G QVSF G DPNQPTF QVSF G

    G ಉҰ཯ /POFqBU.BQ G qBU.BQ H  /POFqBU.BQ BG B qBU.BQ H ݁߹཯ ஋ʹแ·Εͨ΋ͷʹରͯ͠ɺؔ਺ͷ࿈࠯Λ࣮ߦͰ͖Δ