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
610
Try Cats
Scalaの関数型ライブラリCatsをやってみた話です。
fuzyco
January 11, 2018
Tweet
Share
More Decks by fuzyco
See All by fuzyco
Functional Error&Retry Handling
hiroki6
2
600
Extensible Effects: beyond the Monad Transformers
hiroki6
1
840
High Performance Scala/high_performance_scala
hiroki6
4
4.3k
並行四方山話/tales_of_concurrency
hiroki6
0
130
Scalaでの並行・並列処理戦略/strategy-for-concurrency-and-parallel-by-scala
hiroki6
9
3.2k
Monad Error with Cats/monad-error-with-cats
hiroki6
0
640
scala_multi_thread.pdf
hiroki6
0
370
GAEを用いたBQ Load戦略/gae_bq_load_strategy
hiroki6
2
1.9k
Extensible Effects with Scala/eff-with-scala
hiroki6
0
1.1k
Other Decks in Technology
See All in Technology
Security Diaries of an Open Source IAM
ahus1
0
210
vLLM Community Meetup Tokyo #3 オープニングトーク
jpishikawa
0
330
8万デプロイ
iwamot
PRO
2
230
最強のAIエージェントを諦めたら品質が上がった話 / how quality improved after giving up on the strongest AI agent
kt2mikan
0
160
[E2]CCoEはAI指揮官へ。Bedrock×MCPで構築するコスト・セキュリティ自律運用基盤
taku1418
0
130
身体を持ったパーソナルAIエージェントの 可能性を探る開発
yokomachi
1
110
AI は "道具" から "同僚" へ 自律型 AI エージェントの最前線と、AI 時代の人材の在り方 / Colleague in the AI Era - Autonomous AI Seminar 2026 at Niigata
gawa
0
160
わからなくて良いなら、わからなきゃだめなの?
kotaoue
1
290
Claude Code 2026年 最新アップデート
oikon48
11
8.6k
[JAWS DAYS 2026]私の AWS DevOps Agent 推しポイント
furuton
0
150
DevOpsエージェントで実現する!! AWS Well-Architected(W-A) を実現するシステム設計 / 20260307 Masaki Okuda
shift_evolve
PRO
3
640
オレ達はAWS管理をやりたいんじゃない!開発の生産性を爆アゲしたいんだ!!
wkm2
4
500
Featured
See All Featured
DBのスキルで生き残る技術 - AI時代におけるテーブル設計の勘所
soudai
PRO
62
51k
HDC tutorial
michielstock
1
530
Java REST API Framework Comparison - PWX 2021
mraible
34
9.2k
Being A Developer After 40
akosma
91
590k
Lightning Talk: Beautiful Slides for Beginners
inesmontani
PRO
1
480
How GitHub (no longer) Works
holman
316
140k
Code Reviewing Like a Champion
maltzj
528
40k
The browser strikes back
jonoalderson
0
790
Breaking role norms: Why Content Design is so much more than writing copy - Taylor Woolridge
uxyall
0
200
How to build an LLM SEO readiness audit: a practical framework
nmsamuel
1
670
Automating Front-end Workflow
addyosmani
1370
200k
Pawsitive SEO: Lessons from My Dog (and Many Mistakes) on Thriving as a Consultant in the Age of AI
davidcarrasco
0
85
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 ݁߹ ʹแ·Εͨͷʹରͯ͠ɺؔͷ࿈Λ࣮ߦͰ͖Δ