Slide 1

Slide 1 text

5SZ$BUT

Slide 2

Slide 2 text

ΞδΣϯμ w $BUTͱ͸ w $BUTಠࣗͷϞφυ w $BUTΛ௨ֶͯ͠Μͩ͜ͱ

Slide 3

Slide 3 text

$BUTͱ͸ 4DBMB[ͷ಺෦෼྾ʹΑͬͯੜ·Εͨ ؔ਺ܕϓϩάϥϛϯά༻ͷ4DBMBϥΠϒϥϦ ɾ೥ࠒ஀ੜ ɾʹWϦϦʔε ɾݍ DBUFHPSZ ʹ༝དྷ ಡΜͩจݙ ɾೣ൪IUUQFFETJODPNIFSEJOHDBUTKB ɾ4DBMB8JUI$BUT

Slide 4

Slide 4 text

$BUTͷಛ௃ ɾؔ਺ܕϓϩάϥϛϯάΛ࣮ݱ͢ΔͨΊͷ ๛෋ͳܕΫϥεͷఏڙ ɾIBTLFMMʹ͍࣮ۙ૷ &Rɺ4IPXͳͲ

Slide 5

Slide 5 text

$BUTWT4DBMB[ $BUT ɾ৽͍͠σʔλܕ ɾ࣮༻্ඞཁͳશͯͷ൚༻ؔ਺ͷ࣮૷ ΞυϗοΫଟ૬ੑɺUSBJUJNQMJDJU ೣ൪ΑΓҾ༻ 4DBMB[ ɾ৽͍͠σʔλܕ ɾඪ४Ϋϥεͷ֦ு 0QUJPO0QT -JTU0QT ɾ࣮༻্ඞཁͳશͯͷ൚༻ؔ਺ͷ࣮૷ ΞυϗοΫଟ૬ੑɺUSBJUJNQMJDJU ಠश4DBMB[ΑΓҾ༻

Slide 6

Slide 6 text

$BUTWT4DBMB[ &JUIFSa 7BMJEBUFE7BMJEBUJPO 3FBEFS3FBEFS 4UBUF4UBUF 8SJUFS8SJUFS ɾ༻ҙ͞Ε͍ͯΔϝιου͕Ұ෦ҟͳΔ͕ɺ ಉ͡Α͏ͳσʔλܕ͕͋Δ

Slide 7

Slide 7 text

$BUTಠࣗͷϞφυ ɾ&WBM

Slide 8

Slide 8 text

&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

Slide 9

Slide 9 text

&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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

&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 // ... ελοΫΦʔόʔϑϩʔ͕ى͖Δ

Slide 14

Slide 14 text

&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ϝιουΛ࢖ͬͯ͞ΒʹϦϑΝΫλϦϯά

Slide 15

Slide 15 text

&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ϝιουΛ࢖ͬͯ͞ΒʹϦϑΝΫλϦϯά ਖ਼ৗऴྃ

Slide 16

Slide 16 text

&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<">Λฦ͢ܭࢉΛ஗Ԇ͍ͯ͠Δ τϥϯϙϦϯԽ͕ߦΘΕɺؔ਺͕਺चͭͳ͗ Ͱݺ͹Εͳ͘ͳΔ

Slide 17

Slide 17 text

$BUTΛษڧֶͯͯ͠Μͩ͜ͱ ಡΜͩจݙ ɾೣ൪IUUQFFETJODPNIFSEJOHDBUTKB ɾ4DBMB8JUI$BUT ֶͼ ɾϞφυͬͯԿͳͷ͔ ɾ,MFJTMJɺ3FBEFSϞφυ ɾϞφυม׵ࢠ

Slide 18

Slide 18 text

ϞφυͬͯԿͳͷ͔ Ϟφυͱ͸ɺ݁߹཯ͱಉҰ཯Λຬͨ͢࠷খݶͷ ϞφυίϯϏωʔλͷू·Γͷ͍ͣΕ͔Λ࣮૷ͨ͠΋ͷͰ͋Δɻ ΧϥʔίοϓຊΑΓҾ༻

Slide 19

Slide 19 text

ϞφυͬͯԿͳͷ͔ Ϟφυͱ͸ɺ݁߹཯ͱಉҰ཯Λຬͨ͢࠷খݶͷ ϞφυίϯϏωʔλͷू·Γͷ͍ͣΕ͔Λ࣮૷ͨ͠΋ͷͰ͋Δɻ ʁ ΧϥʔίοϓຊΑΓҾ༻

Slide 20

Slide 20 text

ϞφυͬͯԿͳͷ͔ ϞφυΛඥղ͘Ωʔϫʔυ ɾϑΝϯΫλʔ 'VODUPS ɾΞϓϦΧςΟϒϑΝϯΫλʔ "QQMJDBUJWF'VODUPS ͜ͷೋͭ͸ඞͣग़ͯ͘Δ Ϟφυͱ͸ɺ݁߹཯ͱಉҰ཯Λຬͨ͢࠷খݶͷ ϞφυίϯϏωʔλͷू·Γͷ͍ͣΕ͔Λ࣮૷ͨ͠΋ͷͰ͋Δɻ ʁ ΧϥʔίοϓຊΑΓҾ༻

Slide 21

Slide 21 text

Ϟφυ 'VODUPS"QQMZ "QQMJDBUJWF'VODUPS.POBE DBUTʹ͓͍ͯɺ࣍ͷॱͰਐԽ͍ͯ͘͠

Slide 22

Slide 22 text

'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] .... }

Slide 23

Slide 23 text

"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.)

Slide 24

Slide 24 text

"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͸ಉҰ཯Λຬͨ͢

Slide 25

Slide 25 text

.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͸݁߹཯Λຬͨ͢

Slide 26

Slide 26 text

Ϟφυ·ͱΊ Ϟφυͱ͸ɺ݁߹཯ͱಉҰ཯Λຬͨ͢࠷খݶͷ ϞφυίϯϏωʔλͷू·Γͷ͍ͣΕ͔Λ࣮૷ͨ͠΋ͷͰ͋Δɻ DPNQPTF G QVSF G DPNQPTF QVSF G G ಉҰ཯ /POFqBU.BQ G qBU.BQ H /POFqBU.BQ BG B qBU.BQ H ݁߹཯ ஋ʹแ·Εͨ΋ͷʹରͯ͠ɺؔ਺ͷ࿈࠯Λ࣮ߦͰ͖Δ