Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Try Cats
Search
fuzyco
January 11, 2018
Technology
0
510
Try Cats
Scalaの関数型ライブラリCatsをやってみた話です。
fuzyco
January 11, 2018
Tweet
Share
More Decks by fuzyco
See All by fuzyco
Functional Error&Retry Handling
hiroki6
2
430
Extensible Effects: beyond the Monad Transformers
hiroki6
1
640
High Performance Scala/high_performance_scala
hiroki6
4
3.7k
並行四方山話/tales_of_concurrency
hiroki6
0
62
Scalaでの並行・並列処理戦略/strategy-for-concurrency-and-parallel-by-scala
hiroki6
9
2.6k
Monad Error with Cats/monad-error-with-cats
hiroki6
0
470
scala_multi_thread.pdf
hiroki6
0
260
GAEを用いたBQ Load戦略/gae_bq_load_strategy
hiroki6
2
1.6k
Extensible Effects with Scala/eff-with-scala
hiroki6
0
840
Other Decks in Technology
See All in Technology
技育祭2024春 LT Finatextホールディングス
kevinrobot34
1
160
私のRSpecの書き方 / How I write RSpec
tmtms
4
820
WebXR で Web をもっと楽しもう
qst_exe
0
110
期待しすぎずに取り組む両面 TypeScript
shozawa
2
270
ビジネスロジックを「型」で表現するOOPのための関数型DDD / Functional And Type-Safe DDD for OOP
yuitosato
29
11k
8週連続ウェビナー_イチから学ぶFivetran
cmsuzu
0
160
Oracle Database で機械学習を始めよう! Oracle Machine Learning
oracle4engineer
PRO
1
140
2023 Japan AWS Jr.Championsに選出されての振り返りとこれから
hiropy877
1
130
Elementaryを用いたデータ品質の可視化とデータ基盤の運用改善
10xinc
6
1.4k
バッチ処理のSLOをどう設計するか
rynsuke
7
540
LLM + RAG を使った SORACOM Support Bot の裏側の歴史
soracom
PRO
1
630
単回帰分析について数式を追いながら実装してみた
kentaitakura
0
490
Featured
See All Featured
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
11
1.4k
Building a Modern Day E-commerce SEO Strategy
aleyda
15
6.3k
Designing on Purpose - Digital PM Summit 2013
jponch
109
6.4k
What’s in a name? Adding method to the madness
productmarketing
PRO
14
2.6k
The Mythical Team-Month
searls
214
42k
Intergalactic Javascript Robots from Outer Space
tanoku
266
26k
Robots, Beer and Maslow
schacon
PRO
154
7.9k
Making the Leap to Tech Lead
cromwellryan
122
8.4k
Fashionably flexible responsive web design (full day workshop)
malarkey
397
65k
What's in a price? How to price your products and services
michaelherold
236
11k
Put a Button on it: Removing Barriers to Going Fast.
kastner
58
3k
What's new in Ruby 2.0
geeforr
335
31k
Transcript
5SZ$BUT
ΞδΣϯμ w $BUTͱ w $BUTಠࣗͷϞφυ w $BUTΛ௨ֶͯ͠Μͩ͜ͱ
$BUTͱ 4DBMB[ͷ෦྾ʹΑͬͯੜ·Εͨ ؔܕϓϩάϥϛϯά༻ͷ4DBMBϥΠϒϥϦ ɾࠒੜ ɾʹWϦϦʔε ɾݍ DBUFHPSZ ʹ༝དྷ ಡΜͩจݙ ɾೣ൪IUUQFFETJODPNIFSEJOHDBUTKB
ɾ4DBMB8JUI$BUT
$BUTͷಛ ɾؔܕϓϩάϥϛϯάΛ࣮ݱ͢ΔͨΊͷ ๛ͳܕΫϥεͷఏڙ ɾIBTLFMMʹ͍࣮ۙ &Rɺ4IPXͳͲ
$BUTWT4DBMB[ $BUT ɾ৽͍͠σʔλܕ ɾ࣮༻্ඞཁͳશͯͷ൚༻ؔͷ࣮ ΞυϗοΫଟ૬ੑɺUSBJU JNQMJDJU ೣ൪ΑΓҾ༻ 4DBMB[ ɾ৽͍͠σʔλܕ
ɾඪ४Ϋϥεͷ֦ு 0QUJPO0QT -JTU0QT ɾ࣮༻্ඞཁͳશͯͷ൚༻ؔͷ࣮ ΞυϗοΫଟ૬ੑɺUSBJU JNQMJDJU ಠश4DBMB[ΑΓҾ༻
$BUTWT4DBMB[ &JUIFSa 7BMJEBUFE7BMJEBUJPO 3FBEFS3FBEFS 4UBUF4UBUF 8SJUFS8SJUFS ɾ༻ҙ͞Ε͍ͯΔϝιου͕Ұ෦ҟͳΔ͕ɺ ಉ͡Α͏ͳσʔλܕ͕͋Δ
$BUTಠࣗͷϞφυ ɾ&WBM
&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
&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
&WBMʹΑΔ࠶ؼॲཧ def factorial(n: BigInt): BigInt = if(n == 1) n
else n * factorial(n - 1) factorial(50000) // ࣮ߦ ඌ࠶ؼͰͳ͍࠶ؼؔ
&WBMʹΑΔ࠶ؼॲཧ def factorial(n: BigInt): BigInt = if(n == 1) n
else n * factorial(n - 1) factorial(50000) // ࣮ߦ ඌ࠶ؼͰͳ͍࠶ؼؔ ελοΫΦʔόʔϑϩʔ͕ى͖Δ factorial(50000) // java.lang.StackOverflowError // ...
&WBMʹΑΔ࠶ؼॲཧ def factorial(n: BigInt): Eval[BigInt] = if(n == 1) {
Eval.now(n) } else { factorial(n - 1).map(_ * n) } factorial(50000).value // ࣮ߦ &WBMΛ༻͍ͨίʔυʹมߋ
&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 // ... ελοΫΦʔόʔϑϩʔ͕ى͖Δ
&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ϝιουΛͬͯ͞ΒʹϦϑΝΫλϦϯά
&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ϝιουΛͬͯ͞ΒʹϦϑΝΫλϦϯά ਖ਼ৗऴྃ
&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<">Λฦ͢ܭࢉΛԆ͍ͯ͠Δ τϥϯϙϦϯԽ͕ߦΘΕɺ͕ؔचͭͳ͗ ͰݺΕͳ͘ͳΔ
$BUTΛษڧֶͯͯ͠Μͩ͜ͱ ಡΜͩจݙ ɾೣ൪IUUQFFETJODPNIFSEJOHDBUTKB ɾ4DBMB8JUI$BUT ֶͼ ɾϞφυͬͯԿͳͷ͔ ɾ,MFJTMJɺ3FBEFSϞφυ ɾϞφυมࢠ
ϞφυͬͯԿͳͷ͔ Ϟφυͱɺ݁߹ͱಉҰΛຬͨ͢࠷খݶͷ ϞφυίϯϏωʔλͷू·Γͷ͍ͣΕ͔Λ࣮ͨ͠ͷͰ͋Δɻ ΧϥʔίοϓຊΑΓҾ༻
ϞφυͬͯԿͳͷ͔ Ϟφυͱɺ݁߹ͱಉҰΛຬͨ͢࠷খݶͷ ϞφυίϯϏωʔλͷू·Γͷ͍ͣΕ͔Λ࣮ͨ͠ͷͰ͋Δɻ ʁ ΧϥʔίοϓຊΑΓҾ༻
ϞφυͬͯԿͳͷ͔ ϞφυΛඥղ͘Ωʔϫʔυ ɾϑΝϯΫλʔ 'VODUPS ɾΞϓϦΧςΟϒϑΝϯΫλʔ "QQMJDBUJWF'VODUPS ͜ͷೋͭඞͣग़ͯ͘Δ Ϟφυͱɺ݁߹ͱಉҰΛຬͨ͢࠷খݶͷ ϞφυίϯϏωʔλͷू·Γͷ͍ͣΕ͔Λ࣮ͨ͠ͷͰ͋Δɻ
ʁ ΧϥʔίοϓຊΑΓҾ༻
Ϟφυ 'VODUPS"QQMZ "QQMJDBUJWF'VODUPS.POBE DBUTʹ͓͍ͯɺ࣍ͷॱͰਐԽ͍ͯ͘͠
'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] .... }
"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.)
"QQMJDBUJWF'VODUPS "QQMJDBUJWF"QQMZʹ QVSFϝιου "'<"> ΛՃ͍ͯ͠ΔܕΫϥε ϓϦϛςΟϒΛ"QQMJDBUJWFܕʹมͯ͠ɺ ଞͷ"QQMJDBUJWFͱ߹Ͱ͖Δɹ DBUTͷ7BMJEBUFEBQQMJDBUJWFGVODUPSΛܗ͢Δ 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ಉҰΛຬͨ͢
.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݁߹Λຬͨ͢
Ϟφυ·ͱΊ Ϟφυͱɺ݁߹ͱಉҰΛຬͨ͢࠷খݶͷ ϞφυίϯϏωʔλͷू·Γͷ͍ͣΕ͔Λ࣮ͨ͠ͷͰ͋Δɻ DPNQPTF G QVSF G DPNQPTF QVSF G
G ಉҰ /POFqBU.BQ G qBU.BQ H /POFqBU.BQ BG B qBU.BQ H ݁߹ ʹแ·Εͨͷʹରͯ͠ɺؔͷ࿈Λ࣮ߦͰ͖Δ