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
620
0
Share
Try Cats
Scalaの関数型ライブラリCatsをやってみた話です。
fuzyco
January 11, 2018
More Decks by fuzyco
See All by fuzyco
Functional Error&Retry Handling
hiroki6
2
620
Extensible Effects: beyond the Monad Transformers
hiroki6
1
850
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
650
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
How to learn AWS Well-Architected with AWS BuilderCards: Security Edition
coosuke
PRO
0
110
マンション備え付けのネットワークとLTE回線を組み合わせた ネットワークの安定化の考案
harutiro
1
120
「QA=テスト」「シフトレフト=スクラムイベントの参加者の一員」の呪縛を解く。アジャイルな開発を止めないために、10Xで挑んだ「右側のしわ寄せ」解消記 #scrumniigata
nihonbuson
PRO
5
1k
AIの揺らぎに“コシ”を与える階層化品質設計
ickx
0
270
[Scram Fest Niigata2026]Quality as Code〜AIにQAの思考を再現させる試み〜
masamiyajiri
1
310
100マイクロサービスのTerraform/Kubernetes管理地獄から抜け出すためのAI活用術
markie1009
0
120
新卒エンジニア研修、ハンズオンの設計における課題と実践知/ #tachikawaany
nishiuma
2
140
Swift Sequence の便利 API 再発見
treastrain
1
250
Forget technical debt
ufried
0
180
Databricks 月刊サービスアップデートまとめ 2026年04月号
tyosi1212
0
110
全社統制を維持しながら現場負担をどう減らすか〜プラットフォームチームとセキュリティチームで進めたSecurity Hub活用によるAWS統制の見直し〜/secjaws-security-hub-custom-insights
mhrtech
1
360
SLI/SLO、「完全に理解した」から「チョットデキル」へ
maruloop
3
350
Featured
See All Featured
Dominate Local Search Results - an insider guide to GBP, reviews, and Local SEO
greggifford
PRO
0
170
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
34
2.7k
RailsConf 2023
tenderlove
30
1.4k
Practical Orchestrator
shlominoach
191
11k
The Invisible Side of Design
smashingmag
302
52k
Why Our Code Smells
bkeepers
PRO
340
58k
Leading Effective Engineering Teams in the AI Era
addyosmani
9
1.9k
Hiding What from Whom? A Critical Review of the History of Programming languages for Music
tomoyanonymous
2
800
The State of eCommerce SEO: How to Win in Today's Products SERPs - #SEOweek
aleyda
2
10k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
31
3.2k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
254
22k
AI: The stuff that nobody shows you
jnunemaker
PRO
6
630
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 ݁߹ ʹแ·Εͨͷʹରͯ͠ɺؔͷ࿈Λ࣮ߦͰ͖Δ