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
560
Try Cats
Scalaの関数型ライブラリCatsをやってみた話です。
fuzyco
January 11, 2018
Tweet
Share
More Decks by fuzyco
See All by fuzyco
Functional Error&Retry Handling
hiroki6
2
540
Extensible Effects: beyond the Monad Transformers
hiroki6
1
770
High Performance Scala/high_performance_scala
hiroki6
4
4k
並行四方山話/tales_of_concurrency
hiroki6
0
94
Scalaでの並行・並列処理戦略/strategy-for-concurrency-and-parallel-by-scala
hiroki6
9
2.9k
Monad Error with Cats/monad-error-with-cats
hiroki6
0
580
scala_multi_thread.pdf
hiroki6
0
320
GAEを用いたBQ Load戦略/gae_bq_load_strategy
hiroki6
2
1.8k
Extensible Effects with Scala/eff-with-scala
hiroki6
0
1k
Other Decks in Technology
See All in Technology
MySQL Indexes and Histograms – How they really speed up your queries
lefred
0
160
genspark_presentation.pdf
haruki_uiru
1
240
Serverlessだからこそコードと設計にはこだわろう
kenichirokimura
2
950
CARTA HOLDINGS エンジニア向け 採用ピッチ資料 / CARTA-GUIDE-for-Engineers
carta_engineering
0
27k
MCPが変えるAIとの協働
knishioka
1
150
DjangoCon Europe 2025 Keynote - Django for Data Science
wsvincent
0
540
ペアーズにおける評価ドリブンな AI Agent 開発のご紹介
fukubaka0825
9
2.5k
Асинхронная коммуникация в Go: от понятного к душному. Дима Некрасов, Otello, 2ГИС
lamodatech
0
2.1k
社内 Web システムのフロントエンド技術刷新: React Router v7 vs. TanStack Router
musasabibyun
0
140
製造業向けIoTソリューション提案資料.pdf
haruki_uiru
0
240
フルカイテン株式会社 エンジニア向け採用資料
fullkaiten
0
5.5k
Azure Maps Visual in PowerBIで分析しよう
nakasho
0
210
Featured
See All Featured
StorybookのUI Testing Handbookを読んだ
zakiyama
30
5.7k
For a Future-Friendly Web
brad_frost
177
9.7k
Learning to Love Humans: Emotional Interface Design
aarron
273
40k
Bootstrapping a Software Product
garrettdimon
PRO
307
110k
KATA
mclloyd
29
14k
Measuring & Analyzing Core Web Vitals
bluesmoon
7
420
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
34
2.9k
Why Our Code Smells
bkeepers
PRO
336
57k
Building Applications with DynamoDB
mza
94
6.4k
Embracing the Ebb and Flow
colly
85
4.7k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
5
570
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
3.8k
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 ݁߹ ʹแ·Εͨͷʹରͯ͠ɺؔͷ࿈Λ࣮ߦͰ͖Δ