Slide 1

Slide 1 text

scalaz.\/ ͕ศརͩͬͨ࿩ ୈࡾճscalaؔ੢ษڧձ 2016-07-10

Slide 2

Slide 2 text

ࠓ೔͸ scala.Either ͱ scalaz.\/ ͷҧ͍ʹ͍ͭͯ࿩Λ͠·͢

Slide 3

Slide 3 text

scalaz ͷ࿩ͱ͍͏ΑΓ͸ scala.Either ͷ͓͔͠ͳڍಈ΍ scalaz.\/ Ͱͷղܾํ๏Λݟ͍ͯ͘

Slide 4

Slide 4 text

http://www.irasutoya.com/2013/11/blog-post_5898.html ҧ࿨ײײͨ͡Β ͭͬ͜Έ͓ئ͍͠·͢ʂ

Slide 5

Slide 5 text

ཧ࿦ͬΆ͍࿩͸͋·Γ͠ͳ͍ ࣮ફ(࣮૷)ʹΑͬͨ࿩Λ ͢Δͧʂʂʂʂʂʂ

Slide 6

Slide 6 text

͓͠ͳ͕͖ 1. ࣗݾ঺հ 2. scala.Either ֓ཁ 3. scala.Either ͷෆศ 4. ෆศͷݪҼ 5. scalaz.\/

Slide 7

Slide 7 text

ࣗݾ঺հ ୩ޱ ྗే @tanishiking id: tanishiking24 ɾژ౎େֶͰֶੜ΍ͬͯ·͢ ɾ࠷ۙ͸ͯͳΞϧόΠτ ɾڵຯͱͯ͠͸ ɹɹɾ MySQL ɹɹɾ Python / Scala / shell script Scalaྺ: 6ϲ݄͘Β͍?

Slide 8

Slide 8 text

ઌʹ·ͱΊ ɾscala.Either ʹ͸ෆࣗવͳڍಈ͕͍͔ͭ͋͘Δ ɾͦͷҰͭͷղܾࡦͱͯ͠ scalaz.\/ Λ࢖͏ͱ͍͏બ୒ࢶ͕ ͋Δ ɾ؆୯ͳͱ͜Ζ(\/)͔Β scalaz ࢖͍ͬͯ͘ͷ͸ྑͦ͞͏ ɾศརͳͱ͜Ζ͚ͩ࢖͓͏ʂ ɾେࣄͳͷ͸ scala.Either ͷڍಈΛ஌͓ͬͯ͘͜ͱʂ

Slide 9

Slide 9 text

͓͠ͳ͕͖ 1. ࣗݾ঺հ 2. scala.Either ֓ཁ 3. scala.Either ͷෆศ 4. ෆศͷݪҼ 5. scalaz.\/

Slide 10

Slide 10 text

Either ɾscalaඪ४ ɾOptionܕͰnull͔΋͠Εͳ͍ͱ͍͏จ຺ΛදݱͰ͖ͨ ɾྫ֎͕౤͛ΒΕΔͳͲͯ͠ॲཧ͕ࣦഊͨ͠৔߹΋NoneΛฦ͢ʁ ɾ(NoneͩͱΤϥʔ΍ྫ֎ͷ৘ใ͕ࣦΘΕΔ…) ɾEither[A, B]Λ࢖͏͜ͱͰܕ͕A͔B͔ͱ͍͏දݱ͕࣮ݱͰ͖Δ ɾAʹErrorΛ֨ೲͯ͋͛ͨ͠Γ

Slide 11

Slide 11 text

Either ɾEither͸ந৅ΫϥεͰɺͦͷαϒΫϥεͱͯ͠Left,RightΛ࣋ͬͯΔ ɾRightʹਖ਼ৗ஋ɺLeftʹࣦഊͨ࣌͠ͷҟৗ஋ sealed abstract class Either[+A, +B] extends Product with Serializable final case class Left[+A, +B](a: A) extends Either[A, B] final case class Right[+A, +B](b: B) extends Either[A, B] https://github.com/scala/scala/blob/d6f66ec0f38e42c19f79cbe9d32d29c65dee1e05/src/library/scala/util/ Either.scala#L69 https://github.com/scala/scala/blob/d6f66ec0f38e42c19f79cbe9d32d29c65dee1e05/src/library/scala/util/ Either.scala#L182-L202

Slide 12

Slide 12 text

Either def parseInteger(numStr: String): Either[NumberFormatException, Int] = { try { Right(numStr.toInt) } catch { case e: NumberFormatException => Left(e) } } ྫ֎Λ&JUIFSͰϥοϓͯ͠ΈͨΓ

Slide 13

Slide 13 text

Either ɾEitherຊମʹ͸ map / flatMap ͱ͍ͬͨϝιου͸ ੜ͑ͯͳ͍ʂʂʂ ɾ(Right|Left)Projectionͱ͍͏ܕʹੜ͑ͯΔ ɾrightϝιουͰม׵ scala> Right(“12").right.flatMap(parseInteger) res2: scala.util.Either[NumberFormatException,Int] = Right(12) scala> Right(“tanishi").right.flatMap(parseInteger) res3: scala.util.Either[NumberFormatException,Int] = Left(java.lang.NumberFormatException: For input string: "tanishi")

Slide 14

Slide 14 text

Either for-comprehension΋͜Μͳײ͡Ͱ for { rawId <- Right("12").right id <- parseInteger(rawId).right } yield id

Slide 15

Slide 15 text

ศརʂʂ

Slide 16

Slide 16 text

͓͠ͳ͕͖ 1. ࣗݾ঺հ 2. scala.Either ֓ཁ 3. scala.Either ͷෆศ 4. ෆศͷݪҼ 5. scalaz.\/

Slide 17

Slide 17 text

EitherศརͳͷͰ͕͢ ͍͔ͭ͘ෆศͳڍಈ͕…

Slide 18

Slide 18 text

Either - ֬ೝ scala ͷ forࣜ͸ίϯύΠϧ࣌ʹ಺෦తʹ map / flatMap / withFilter / filter / foreach ͱ͍ͬͨϝιουͷ૊Έ߹Θͤʹม׵͞ΕΔ

Slide 19

Slide 19 text

Ұͭ໨ for { a <- Right(1).right b = a + 1 } yield b

Slide 20

Slide 20 text

for-comprehensionͰ ୅ೖͬΆ͍͜ͱ͕Ͱ͖ͳ͍ for { a <- Right(1).right b = a + 1 } yield b :24: error: value map is not a member of Product with Serializable with scala.util.Either[Nothing,(Int, Int)] a <- Right(1).right FJUIFS͔Βग़͖ͯͨ஋Λӈࣜʹ࣋ͭ࣌

Slide 21

Slide 21 text

ೋͭ໨ for { (a, b) <- Right((1, 2)).right } yield a + b

Slide 22

Slide 22 text

for-comprehensionͰ ύλʔϯϚονͰ͖ͳ͍໰୊ for { (a, b) <- Right((1, 2)).right } yield a + b :19: error: constructor cannot be instantiated to expected type; found : (T1, T2) required: scala.util.Either[Nothing,(Int, Int)] (a, b) <- Right((1, 2)).right ^

Slide 23

Slide 23 text

for-comprehensionͰ ύλʔϯϚονͰ͖ͳ͍໰୊ (for { a <- Right(1).right if a > 0 } yield a) match { case Right(num) => println(num) case Left(_) => println("left!!") } :28: error: constructor cannot be instantiated to expected type; found : scala.util.Right[A,B] required: Option[scala.util.Either[Nothing,Int]] case Right(n) => println(n) ύλʔϯϚον͡Όͳ͍͚Ͳ͜Ε΋μϝ

Slide 24

Slide 24 text

ͪͳΈʹ྆ํͱ΋ OptionͰ͸࣮ݱͰ͖Δ for { (a, b) <- Some((1, 2)) } yield a + b res0: Option[Int] = Some(3) for { a <- Some(1) b = a + 1 } yield b res1: Option[Int] = Some(2)

Slide 25

Slide 25 text

͓͠ͳ͕͖ 1. ࣗݾ঺հ 2. scala.Either ֓ཁ 3. scala.Either ͷෆศ 4. ෆศͷݪҼ 5. scalaz.\/

Slide 26

Slide 26 text

scala -Xprint:parser(typer)

Slide 27

Slide 27 text

֬ೝ scala.Either ΍ scalaz.\/ ʹ͸ withFilter ͕࣮૷ ͞Ε͓ͯΒͣ withFilter ͷ୅ΘΓʹ filter ͕࢖༻͞ ΕΔ ࠓճͷ࿩Ͱ͸ filter ͱ withFilter ͷҧ͍͸ॏཁͰ͸ ͳ͍ͷͰ໨ΛͭΉΓ·͢

Slide 28

Slide 28 text

for-comprehensionͰ ୅ೖͬΆ͍͜ͱ͕Ͱ͖ͳ͍ for { a <- Right(1).right b = a + 1 } yield b ͍͍ͩͨ͜Μͳײ͡ʹͳΔͬΆ͍ Right(1).right.map(a => { val b = a + 1; (a, b) }).map(_ match { case ((a, b)) => b })

Slide 29

Slide 29 text

for-comprehensionͰ ୅ೖͬΆ͍͜ͱ͕Ͱ͖ͳ͍ Right(1).right.map(a => { val b = a + 1; (a, b) }).map(_ match { case ((a, b)) => b }) ͜͜ͷฦΓ஋͸ Right((1, 2))

Slide 30

Slide 30 text

for-comprehensionͰ ୅ೖͬΆ͍͜ͱ͕Ͱ͖ͳ͍ Right(1).right.map(a => { val b = a + 1; (a, b) }).map(_ match { case ((a, b)) => b }) ͜͜ͷฦΓ஋͸ Right((1, 2)) map ΍ flatMap ͕ੜ͑ͯΔͷ͸ RightProjection!!!!!

Slide 31

Slide 31 text

for-comprehensionͰ ୅ೖͬΆ͍͜ͱ͕Ͱ͖ͳ͍ ɾ(Right|Left)Projection.map() ͕ฦ͢ܕ͸ Either ɾ͔͠͠ Either ʹ͸ map ΋ flatMap ΋ੜ͑ͯͳ͍ ɾEither ʹ map ͱ͔͕ੜ͑ͯͨΒྑ͍ͷʹ…

Slide 32

Slide 32 text

for-comprehensionͰ ύλʔϯϚονͰ͖ͳ͍໰୊ for { (a, b) <- Right((1, 2)).right } yield a + b ͍͍ͩͨ͜Μͳײ͡ʹͳΔͬΆ͍ Right((1, 2)).right.filter(_ match { case (_, _) => true case _ => false }).map(_ match { case (a, b) => a + b })

Slide 33

Slide 33 text

for-comprehensionͰ ύλʔϯϚονͰ͖ͳ͍໰୊ Right((1, 2)).right.filter(_ match { case (_, _) => true case _ => false }).map(_ match { case (a, b) => a + b }) λϓϧ͕λϓϧ͔ΛXJUI'JMUFSͰݕࠪ

Slide 34

Slide 34 text

for-comprehensionͰ ύλʔϯϚονͰ͖ͳ͍໰୊ Right((1, 2)).right.filter(_ match { case (_, _) => true case _ => false }).map(_ match { case (a, b) => a + b }) :19: error: constructor cannot be instantiated to expected type; found : (T1, T2) required: scala.util.Either[Nothing,(Int, Int)] (a, b) <- Right((1, 2)).right ^

Slide 35

Slide 35 text

for-comprehensionͰ ύλʔϯϚονͰ͖ͳ͍໰୊ RightProjection.filter ͷ࣮૷ΛݟͯΈΔͱ def filter[X](p: B => Boolean): Option[Either[X, B]] = e match { case Left(_) => None case Right(b) => if(p(b)) Some(Right(b)) else None } https://github.com/scala/scala/blob/d6f66ec0f38e42c19f79cbe9d32d29c65dee1e05/src/library/ scala/util/Either.scala#L546-L549

Slide 36

Slide 36 text

for-comprehensionͰ ύλʔϯϚονͰ͖ͳ͍໰୊ RightProjection.filter ͷ࣮૷ΛݟͯΈΔͱ def filter[X](p: B => Boolean): Option[Either[X, B]] = e match { case Left(_) => None case Right(b) => if(p(b)) Some(Right(b)) else None } https://github.com/scala/scala/blob/d6f66ec0f38e42c19f79cbe9d32d29c65dee1e05/src/library/ scala/util/Either.scala#L546-L549

Slide 37

Slide 37 text

for-comprehensionͰ ύλʔϯϚονͰ͖ͳ͍໰୊ Right((1, 2)).right.filter(_ match { case (_, _) => true case _ => false }).map(_ match { case (a, b) => a + b }) :19: error: constructor cannot be instantiated to expected type; found : (T1, T2) required: scala.util.Either[Nothing,(Int, Int)] (a, b) <- Right((1, 2)).right ^ Either[Nothing, (Int, Int)]

Slide 38

Slide 38 text

/ || ̄ ̄|| ∧_∧ |.....||__|| (     )  どうしてこうなった・・・ | ̄ ̄\三⊂/ ̄ ̄ ̄/ |    | ( ./     /  ___

Slide 39

Slide 39 text

for-comprehensionͰ ύλʔϯϚονͰ͖ͳ͍໰୊ ɾfilter ͕ Option[Either[X,B]] Λฦ͢ͷ͕ݪҼ ɾfilter ͕ Either[X,B] Λฦͯ͘͠ΕΔͱOK ɾfilter ʹҾ͔͔ͬΒͳ͔ͬͨͱ͖ʹʮࣗવͳʯLeft஋Λ ఆٛͰ͖Δͱྑͦ͞͏ ɾEither[String, B] ͳΒ Left(“”) ɾEither[Int, B] ͳΒ Left(0) ɾΈ͍ͨʹฦ͢ͱࣗવͬΆ͘ͳ͍ʁ

Slide 40

Slide 40 text

for-comprehensionͰ ύλʔϯϚονͰ͖ͳ͍໰୊ ๻ͷߟ͍͖͑ͨ͞ΐʔͷfilter(ະ׬) def filter[X](p: B => Boolean): Either[X, B] = e match { case Left(e) => Left(e) case Right(b) => if(p(b)) Right(b) ɹɹ else Left(<͍͍ײ͡ͷ஋>: X) }

Slide 41

Slide 41 text

͓͠ͳ͕͖ 1. ࣗݾ঺հ 2. scala.Either ֓ཁ 3. scala.Either ͷෆศ 4. ෆศͷݪҼ 5. scalaz.\/

Slide 42

Slide 42 text

͜Ε·Ͱͷ·ͱΊ ɾRightProjection Ͱͳ͘ Either ʹ map/flatMap ͕ੜ͑ͯΕ͹خ͍͠ ɾfilter ͕ Either[X,B] Λฦͯ͠ཉ͍͠ ɾͦͷͨΊ filter ͰϚον͠ͳ͔ͬͨͱ͖ʹࣗવͳ Left஋ΛͱΔૢ࡞͕Ͱ͖Δͱྑͦ͞͏

Slide 43

Slide 43 text

scalaz ɾศརܕΫϥε ɾศརσʔλܕ ɾඪ४Ϋϥε֦ுͷͨΊͷศར implicit conversion ͕ू߹ͨ͠ศརϥΠϒϥϦ(ͱ͍͏ೝࣝ)

Slide 44

Slide 44 text

scalaz.\/ sealed abstract class \/[+A, +B] extends Product with Serializable final case class -\/[+A](a: A) extends (A \/ Nothing) final case class \/-[+B](b: B) extends (Nothing \/ B) scala.Either ͱҧͬͯ scalaz.\/ ʹ͸ map ΍ flatMap ͕ੜ ͑ͯΔʂ

Slide 45

Slide 45 text

for-comprehensionͰ ୅ೖͬΆ͍͜ͱ͕Ͱ͖ͳ͍ scalaz.\/ ʹ͸ map ΍ flatMap ͕ੜ͑ͯΔʂʂ for { a <- 1.right[String] b = a + 1 } yield b res3: scalaz.\/[String,Int] = \/-(2)

Slide 46

Slide 46 text

for-comprehensionͰ ύλʔϯϚονͰ͖ͳ͍໰୊ ͓͞Β͍: RightProjection.filter ͷ࣮૷ def filter[X](p: B => Boolean): Option[Either[X, B]] = e match { case Left(_) => None case Right(b) => if(p(b)) Some(Right(b)) else None }

Slide 47

Slide 47 text

for-comprehensionͰ ύλʔϯϚονͰ͖ͳ͍໰୊ ๻ͷߟ͍͖͑ͨ͞ΐʔͷfilter def filter[X](p: B => Boolean): Either[X, B] = e match { case Left(e) => Left(e) case Right(b) => if(p(b)) Right(b) ɹɹ else Left(<͍͍ײ͡ͷ஋>: X) }

Slide 48

Slide 48 text

for-comprehensionͰ ύλʔϯϚονͰ͖ͳ͍໰୊ scalaz.\/.filter ͷ࣮૷͸ def filter[AA >: A](p: B => Boolean) (implicit M: Monoid[AA]): (AA \/ B) = this match { case -\/(_) => this case \/-(b) => if(p(b)) this else -\/(M.zero) } https://github.com/scalaz/scalaz/blob/series/7.3.x/core/src/main/scala/scalaz/ Either.scala#L145-L150

Slide 49

Slide 49 text

for-comprehensionͰ ύλʔϯϚονͰ͖ͳ͍໰୊ Monoid : (Monad͡Όͳ͍Αʂ) ू߹(ܕ)Sͱͦͷ্ͷೋ߲ԋࢉ |+| ʹ͍ͭͯҎԼͷنଇΛຬͨ͢ ू߹ͱೋ߲ԋࢉͷ૊Έ߹Θͤ 1. ೋ߲ԋࢉ ͕ू߹ʹ͍ͭͯด͍ͯ͡Δ (ೋ߲ԋࢉͷҾ਺ͱฦΓ஋ͷܕ͕ಉ͡) 2. ԋࢉ͕݁߹཯Λຬͨ͢ (a |+| b) |+| c == a |+| (b |+| c) 3. ୯Ґݩe ͕ଘࡏ͢Δ (forall s: S) s |+| e == e && e |+| s == e ࠓճॏཁͳͷ͸ ͜ͷੑ࣭ʂʂ

Slide 50

Slide 50 text

for-comprehensionͰ ύλʔϯϚονͰ͖ͳ͍໰୊ ྫ: Int ͱ + ͳΒ୯Ґݩ͸ 0 0 + x = x + 0 = x (where x: Int) String ͱ + ͳΒ୯Ґݩ͸ “” “” + s = s + “” = s (where s: String)

Slide 51

Slide 51 text

for-comprehensionͰ ύλʔϯϚονͰ͖ͳ͍໰୊ Monoid[X].zero ͰܕXͷ(Ճ๏ʹ͍ͭͯͷ(?))୯ҐݩΛͱΔ Monoid[Int].zero = 0 Monoid[String].zero = “” Monoid[List[Int]] = List() Ͳ͜Ͱఆٛ͞ΕͯΔͷ͔

Slide 52

Slide 52 text

for-comprehensionͰ ύλʔϯϚονͰ͖ͳ͍໰୊ Int΍ΒString΍Β͍ΖΜͳܕͷMonoidͱͯ͠ͷੑ࣭͕ implicit object ͱͯ͠ scalaz಺Ͱఆٛ͞ΕͯΔ trait StringInstances { implicit object stringInstance extends Monoid[String] with /*தུ*/ { // தུ def zero: String = "" // தུ } } https://github.com/scalaz/scalaz/blob/series/7.3.x/core/src/main/scala/scalaz/std/ String.scala#L5

Slide 53

Slide 53 text

for-comprehensionͰ ύλʔϯϚονͰ͖ͳ͍໰୊ scalaz.\/.filter ͷ࣮૷͸ def filter[AA >: A](p: B => Boolean) (implicit M: Monoid[AA]): (AA \/ B) = this match { case -\/(_) => this case \/-(b) => if(p(b)) this else -\/(M.zero) } aʹͳΔ͍ΖΜͳܕʹ͍ͭͯ౷Ұతͳ ΠϯλʔϑΣʔε .POPJE<9>[FSP ͰྵݩΛฦ͢͜ͱ͕Ͱ͖Δ

Slide 54

Slide 54 text

for-comprehensionͰ ύλʔϯϚονͰ͖ͳ͍໰୊ 1.right[String].filter(_ > 0) res25: scalaz.\/[String,Int] = \/-(1) 1.right[String].filter(_ < 0) res26: scalaz.\/[String,Int] = -\/()

Slide 55

Slide 55 text

for-comprehensionͰ ύλʔϯϚονͰ͖ͳ͍໰୊ for { (a, b) <- (1, 2).right[String] } yield a + b res27: scalaz.\/[String,Int] = \/-(3) (warning͕ग़·͕͢withFilterͷ୅ΘΓʹfilterΛ࢖ͬͨͧʂͬͯ ͍͏ܯࠂ) OK͡ΌΜʂʂ

Slide 56

Slide 56 text

·ͱΊ ɾscala.Either ʹ͸ෆࣗવͳڍಈ͕͍͔ͭ͋͘Δ ɾͦͷҰͭͷղܾࡦͱͯ͠ scalaz.\/ Λ࢖͏ͱ͍͏બ୒ࢶ͕ ͋Δ ɾ؆୯ͳͱ͜Ζ(\/)͔Β scalaz ࢖͍ͬͯ͘ͷ͸ྑͦ͞͏ ɾศརͳͱ͜Ζ͚ͩ࢖͓͏ʂ ɾେࣄͳͷ͸ scala.Either ͷڍಈΛ஌͓ͬͯ͘͜ͱʂ

Slide 57

Slide 57 text

ࢀߟ HaskellͷdoͱScalaͷforࣜͱEitherͱMonadPlus http://d.hatena.ne.jp/xuwei/20130517/1368814058 ओཁͳܕΫϥεͷ঺հ https://gist.github.com/gakuzzzz/8d497609012863b3ea50 scalaz https://github.com/scalaz/scalaz ಠश Scalaz — \/ http://eed3si9n.com/learning-scalaz/ja/Either.html