Slide 1

Slide 1 text

&YUFOTJCMF&⒎FDUT XJUI4DBMB

Slide 2

Slide 2 text

Ϟνϕʔγϣϯ ݩͷࢿྉ͸ͪ͜ΒͰ͢ IUUQTXXXTMJEFTIBSFOFU4BOTIJSP:PTIJEB FYUFOTJCMFF⒎FDUTJOEPUUZ 4DBMB.BUTVSJʹ͓͍ͯIBMDBUYB͞Μͷ ʮ&YUFOTJCMF&⒎FDUTJO%PUUZʯ ͷ಺༰͕೉ͯ͘͠Θ͔Βͳ͔ͬͨͷͰɺ ࣗ෼ͳΓʹղऍͯ͠·ͱΊͯΈ·ͨ͠ɻ

Slide 3

Slide 3 text

ΞδΣϯμ ɾ%PUUZͱ͸ ɾ&YUFOTJCMF&⒎FDUTͱ͸ ɾϞφυม׵ࢠ ɾϞφυελοΫ ɾ&YUFOTJCMF&⒎FDUTJO4DBMB 4DBMB.BUTVSJͷεϥΠυͱղઆ৫Γަͥͯ࿩͍͖ͯ͠·͢

Slide 4

Slide 4 text

ಘΒΕΔ஌ࣝ ɾϞφυม׵ࢠ ɾϞφυελοΫ ɾ'SFFϞφυ ɾ&YUFOTJCMF&⒎FDUT EPUUZ͸ϝΠϯ͡Ό͋Γ·ͤΜ

Slide 5

Slide 5 text

ΞδΣϯμ ɾ%PUUZͱ͸ ɾ&YUFOTJCMF&⒎FDUTͱ͸ ɾϞφυม׵ࢠ ɾϞφυελοΫ ɾ&YUFOTJCMF&⒎FDUTJO%PUUZ

Slide 6

Slide 6 text

%PUUZͱ͸ w ࣍ੈ୅ͷ4DBMBίϯύΠϥ w 4DBMB͔Βඪ४ʹͳΔΒ͍͠ w ݱࡏͷ࠷৽ͷόʔδϣϯ͸

Slide 7

Slide 7 text

%PUUZͷಛ௃ ɾ&OVNT ɾ5ZQF-BNCEBT ɾ*OUFSTFDUJPO5ZQFT ɾ6OJPO5ZQFT ɾ*NQMJDJU'VODUJPO5ZQFT ɾFUD

Slide 8

Slide 8 text

5ZQF-BNCEBT UZQF1BJS<"> " " UZQF1BJS<"> " " WBMQ1BJS<*OU> %PUUZ 4DBMB <Ҿ༻IUUQTXXXTMJEFTIBSFOFU4BOTIJSP:PTIJEBFYUFOTJCMFF⒎FDUTJOEPUUZ>

Slide 9

Slide 9 text

5ZQF-BNCEBT type FreeMonad[F[_]] = Monad[({ type λ[A] = Free[F, A] })#λ] type FreeMonad[F[_]] = Monad[[A] => Free[F, A]] %PUUZ 4DBMB ܕͷ෦෼ద༻͕௚઀ॻ͚Δ <Ҿ༻IUUQTXXXTMJEFTIBSFOFU4BOTIJSP:PTIJEBFYUFOTJCMFF⒎FDUTJOEPUUZ>

Slide 10

Slide 10 text

6OJPO5ZQF val x: String | Int = if util.Random.nextBoolean() then "hoge" else 0 <Ҿ༻IUUQTXXXTMJEFTIBSFOFU4BOTIJSP:PTIJEBFYUFOTJCMFF⒎FDUTJOEPUUZ>

Slide 11

Slide 11 text

ΞδΣϯμ ɾ%PUUZͱ͸ ɾ&YUFOTJCMF&⒎FDUTͱ͸ ɾϞφυม׵ࢠ ɾϞφυελοΫ ɾ&YUFOTJCMF&⒎FDUTJO%PUUZ

Slide 12

Slide 12 text

&YUFOTJCMF&⒎FDUT F⒎ ͱ͸ ϞφυελοΫΛ࣮ݱͨ͠΋ͷ Ϟφυม׵ࢠ ϞφυελοΫ ϞφυͷੵΈॏͶ Ϟφυͷแؚ 4UBUF5 0QUJPO 0QUJPO 4UBUF5 4UBUF 4UBUF 0QUJPO 0QUJPO

Slide 13

Slide 13 text

Ϟφυม׵ࢠ case class User(id: Long, firstName: Option[String], lastName: Option[String]) def getUser(id: Long): Either[String, User] = ??? def getUserName(id: Long): Either[String, Option[String]] = for { user <- getUser(id) // Either } yield for { first <- user.firstName // Option last <- user.lastName } yield s"$first $last" import cats.data.OptionT import cats.implicits._ type StringEither = [A] => Either[String, A] def getUserName(id: Long): Either[String, Option[String]] = (for { user <- OptionT.liftF(getUser(id)) first <- OptionT.fromOption[StringEither](user.firstName) last <- OptionT.fromOption[StringEither](user.lastName) } yield s"$first $last").value GPS͕ࣜ࿈࠯ͯ͠ॻ͖ͮΒͯ͘ಡΈͮΒ͍ ෳ਺ͷϞφυ͕ࠞࡏ͢Δ৔߹ GPSࣜҰͭͰॻ͚Δ

Slide 14

Slide 14 text

Ϟφυม׵ࢠͷ໰୊఺ ߹੒͢ΔϞφυ͕૿͑Δͨͼʹɺܭࢉͷޮ཰͕མͪΔ ԼҐͷϞφυͷॲཧΛߦ͏ͷʹɺҰʑMJGUΛߦ͏ඞཁ͕͋Δ Ϟφυͷ߹੒ॱ͸ݻఆ͞Ε͍ͯͯɺ్தͰೖΕସ͑Δ͜ͱ͕Ͱ͖ͳ͍ ϞφυΛ߹੒͢Δॱ൪ʹΑͬͯɺܭࢉͷҙຯ͕มΘΔ 4UBUF5 0QUJPO 0QUJPO 4UBUF5

Slide 15

Slide 15 text

Ϟφυม׵ࢠͷ໰୊఺ ߹੒͢ΔϞφυ͕૿͑Δͨͼʹɺܭࢉͷޮ཰͕མͪΔ package cats package data final case class OptionT[F[_], A](value: F[Option[A]]) { def flatMap[B](f: A => OptionT[F, B])(implicit F: Monad[F]): OptionT[F, B] = flatMapF(a => f(a).value) def flatMapF[B](f: A => F[Option[B]])(implicit F: Monad[F]): OptionT[F, B] = OptionT(F.flatMap(value)(_.fold(F.pure[Option[B]](None))(f))) } ճϧʔϓ͕૸Δ

Slide 16

Slide 16 text

Ϟφυม׵ࢠͷ໰୊఺ ԼҐͷϞφυͷॲཧΛߦ͏ͷʹɺҰʑMJGUΛߦ͏ඞཁ͕͋Δ import cats.data.{ OptionT, StateT } import cats.instances.list._ import cats.instances.either._ type StringEither = [A] => Either[String, A] type OptionTEither = [A] => OptionT[StringEither, A] type StateTOptionTEither[S, C, A] = StateT[[C] => OptionTEither[C], S, A] def getUser(id: Long): Either[String, User] = ??? def getState(id: Long): StateTOptionTEither[Int, User, Long] = StateT.liftF { OptionT.liftF { getUser(id) }.map { user => user.id } } ԼҐͷ&JUIFSͷॲཧΛߦ͏ͨΊʹɺ ೋճMJGUΛݺΜͰ͍Δ

Slide 17

Slide 17 text

Ϟφυม׵ࢠͷ໰୊఺ Ϟφυͷ߹੒ॱ͸ݻఆ͞Ε͍ͯͯɺ్தͰೖΕସ͑Δ͜ͱ͕Ͱ͖ͳ͍ ϞφυΛ߹੒͢Δॱ൪ʹΑͬͯɺܭࢉͷҙຯ͕มΘΔ import cats.data.{OptionT, State, StateT} import cats.instances.either._ import cats.instances.option._ // StateT[Option, Int, Int] StateT.modify[Option, Int] { _+1 }.flatMap { _ => StateT.liftF[Option, Int, Int](None) }.run(10) // None type IntState = [A] => State[Int, A] // OptionT[IntState, Unit] OptionT.liftF[IntState, Unit] { State.modify{ _+1 } }.flatMap { _ => OptionT.none[IntState, Unit] }.value.run(10).value // (11, None) ԼҐͷϞφυ͕0QUJPOͳͷͰɺ ్தͰࣦഊ͢Δͱ/POFʹͳΔ ԼҐͷϞφυ͕4UBUFͳͷͰɺ ్தͰࣦഊͯ͠΋಺෦ঢ়ଶ͸อ࣋͞ΕΔ

Slide 18

Slide 18 text

ϞφυελοΫ Ϟφυม׵ࢠͷ໰୊Λղܾ͢Δख๏ ߹੒͢ΔϞφυ͕૿͑Δͨͼʹɺܭࢉͷޮ཰͕མͪΔ ԼҐͷϞφυͷॲཧΛߦ͏ͷʹɺҰʑMJGUΛߦ͏ඞཁ͕͋Δ Ϟφυͷ߹੒ॱ͸ݻఆ͞Ε͍ͯͯɺ్தͰೖΕସ͑Δ͜ͱ͕Ͱ͖ͳ͍ શͯͷܭࢉΛҰͭͷϞφυͷதͰߦ͏ ϞφυΛ߹੒͢Δॱ൪ʹΑͬͯɺܭࢉͷҙຯ͕มΘΔ 4UBUF 4UBUF 0QUJPO 0QUJPO

Slide 19

Slide 19 text

&YUFOTJCMF&⒎FDUT DBUDI SVO3FBEFS ɾϞφυͷॲཧΛΫϥΠΞϯτͱϋϯυϥͷ૬ޓ࡞༻Ͱଊ͑Δ ɾϞφυม׵ࢠͷϞφυελοΫΛɺҕৡؔ܎ͷνΣʔϯͱͯ͠ଊ͑Δ SVO&SSPS SVO4UBUF ҕৡ ҕৡ ҕৡ MJGU͕ෆཁɺ֊૚͕ͳ͍ ϋϯυϥ ΫϥΠΞϯτϓϩάϥϜ ϦΫΤετ HFU UFMM UISPX

Slide 20

Slide 20 text

&YUFOTJCMF&⒎FDUT &YUFOTJCMF&⒎FDUT cc 'SFF.POBE 0QFO6OJPO

Slide 21

Slide 21 text

͔͜͜Β͕ຊ୊ ݩࢿྉͷҎ߱ ͔͜͜Βઌͷαϯϓϧίʔυ͸ɺ EPUUZͷߏจͰॻ͔ͳͯ͘΋͍͚Δ෦෼͸ 4DBMBͰॻ͔Ε͍ͯ·͢

Slide 22

Slide 22 text

ΞδΣϯμ ɾ%PUUZͱ͸ ɾ&YUFOTJCMF&⒎FDUTͱ͸ ɾϞφυม׵ࢠ ɾϞφυελοΫ ɾ&YUFOTJCMF&⒎FDUTJO4DBMB 4DBMB.BUTVSJͷεϥΠυͱղઆ৫Γަͥͯ࿩͍͖ͯ͠·͢

Slide 23

Slide 23 text

࿩͢͜ͱ w 'SFF w 'SFFS w $PZPOFEB w 5ZQFBMJHOFE2VFVF w 'BTU'SFFS w &YUFOTJCMF&⒎FDUT w 0QFO6OJPO

Slide 24

Slide 24 text

'SFF.POBE case class Pure[F[_], A](a: A) extends Free[F, A] case class Impure[F[_], A](ff: F[Free[F, A]]) extends Free[F, A] sealed trait Free[F[_], A] { def map[B](f: A => B)(implicit F: Functor[F]): Free[F, B] = flatMap(a => Pure(f(a))) def flatMap[B](f: A => Free[F, B])(implicit F: Functor[F]): Free[F, B] = this match { case Pure(a) => f(a) case Impure(ff) => { Impure(F.map(ff)(_.flatMap(f))) } } } def lift[F[_], A](fa: F[A])(implicit F: Functor[F]): Free[F, A] = Impure(F.map(fa)(a => Pure(a))) 'VODUPSΛϞφυʹม׵͢Δ ७ਮͳܭࢉ ෭࡞༻෇͖ͷܭࢉ

Slide 25

Slide 25 text

'SFF8SJUFS type Writer[W, A] = Free[[T] = Tell[W, T], A] // w: ग़ྗ஋ a: ܭࢉ͞Εͨ஋ case class Tell[W, A](w: W, a: A) { def map[B](f: A => B) = Tell(w, f(a)) } def tell[W](w: W): Writer[W, Unit] = Free.lift[[T] = Tell[W, T], Unit](Tell(w, ())) ܭࢉ͞Εͨ஋ͱ͸ผʹσʔλͷετϦʔϜΛੜ੒͢ΔϞφυ

Slide 26

Slide 26 text

'SFF8SJUFS type Writer[W, A] = Free[[T] = Tell[W, T], A] // w: ग़ྗ஋ a: ܭࢉ͞Εͨ஋ case class Tell[W, A](w: W, a: A) { def map[B](f: A => B) = Tell(w, f(a)) } def tell[W](w: W): Writer[W, Unit] = Free.lift[[T] = Tell[W, T], Unit](Tell(w, ())) def runAsList[W, A](free: Writer[W, A]): (List[W], A) = free match { case pure: Free.Pure[[T] = Tell[W, T], A] => (Nil, pure.a) case impure: Free.Impure[[T] = Tell[W, T], A] => runAsList(impure.ff.a) match { case (ws, a) => (impure.ff.w :: ws, a) } } val e = for { _ <- tell("hoge") _ <- tell("fuga") } yield () runAsList(e) // (List(hoge, fuga),()) 8SJUFS͕'VODUPSͰ͋Ε͹ɺ ϞφυʹͳΔ ܭࢉ͞Εͨ஋ʹͱ͸ผʹσʔλͷετϦʔϜΛੜ੒͢ΔϞφυ

Slide 27

Slide 27 text

'SFF8SJUFS implicit def tellFunctor[W] = new Functor[[A] = Tell[W, A]] { def map[A, B](fa: Tell[W, A])(f: A => B): Tell[W, B] = fa.map(f) } implicit def writerFunctor[W] = new Functor[[A] = Writer[W, A]] { def map[A, B](fa: Writer[W, A])(f: A => B): Writer[W, B] = fa.map(f) } 'VODUPSͷܕΫϥεΛ࣮૷͢Δඞཁ͕͋Δ

Slide 28

Slide 28 text

'SFF8SJUFS type Writer[W, A] = Free[[T] = Tell[W, T], A] case class Tell[W, A](w: W, a: A) { def map[B](f: A => B) = Tell(w, f(a)) } def tell[W](w: W): Writer[W, Unit] = Free.lift[[T] = Tell[W, T], Unit](Tell(w, ())) implicit def tellFunctor[W] = new Functor[[A] = Tell[W, A]] { def map[A, B](fa: Tell[W, A])(f: A => B): Tell[W, B] = fa.map(f) } implicit def writerFunctor[W] = new Functor[[A] = Writer[W, A]] { def map[A, B](fa: Writer[W, A])(f: A => B): Writer[W, B] = fa.map(f) } def runAsList[W, A](free: Writer[W, A]): (List[W], A) = free match { case pure: Free.Pure[({type F[T] = Tell[W, T]})#F, A] => (Nil, pure.a) case impure: Free.Impure[({type F[T] = Tell[W, T]})#F, A] => runAsList(impure.ff.a) match { case (ws, a) => (impure.ff.w :: ws, a) } } val e = for { _ <- tell("hoge") _ <- tell("fuga") } yield () runAsList(e) // (List(hoge, fuga),())

Slide 29

Slide 29 text

'SFF.BZCF type ConstUnit[A] = Unit type Maybe[A] = Free[ConstUnit, A] def some[A](a: A): Maybe[A] = Free.Pure[ConstUnit, A](a) def none[A]: Maybe[A] = Free.Impure[ConstUnit, A]((): ConstUnit[Maybe[A]]) def safeDiv(n: Int, d: Int): Maybe[Int] = if (d == 0) none else some(n / d) implicit val ConstUnitFunctor = new Functor[ConstUnit] { def map[A, B](fa: ConstUnit[A])(f: A => B): ConstUnit[B] = (): ConstUnit[B] } val r = for { n <- safeDiv(4, 2) m <- safeDiv(n, 0) // none } yield m def maybe[A](maybe: Maybe[A])(default: A): A = maybe match { case Pure(a) => a case Impure(()) => default } assert(maybe(r)(42) == 42) // r͕noneͳͷͰɺdefaultͷ42͕ద༻͞ΕΔ $POTU6OJU͕'VODUPSͳͷͰɺ ϞφυʹͳΔ

Slide 30

Slide 30 text

'SFFS.POBE 'VODUPSͷ੍໿ͳ͠ʹϞφυʹͳΔ case class Pure[F[_], A](a: A) extends Freer[F, A] case class Impure[F[_], A, B](fa: F[A], f: A => Freer[F, B]) extends Freer[F, B] sealed trait Freer[F[_], A] { def map[B](f: A => B): Freer[F, B] = flatMap(a => Pure(f(a))) def flatMap[B](f: A => Freer[F, B]): Freer[F, B] = this match { case Pure(a) => f(a) case Impure(fa, g) => Impure(fa, (a: Any) => g(a).flatMap(f)) } } object Freer { def lift[F[_], A](fa: F[A]): Freer[F, A] = Impure(fa, a => Pure[F, A](a)) } $PZPOFEBͱΏ͏NBQΛ࣋ͭߏ଄Λ'SFFʹՃ͑ͨ΋ͷ

Slide 31

Slide 31 text

'SFFS8SJUFS type Writer[W, A] = Freer[[T] = Tell[W, T], A] case class Tell[W, A](w: W, a: A) { def map[B](f: A => B) = Tell(w, f(a)) } def tell[W](w: W): Writer[W, Unit] = Freer.lift[[T] = Tell[W, T], Unit](Tell(w, ())) def runAsList[W, A, B](freer: Writer[W, A]): (List[W], A) = freer match { case pure: Freer.Pure[({type F[T] = Tell[W, T]})#F, A] => (Nil, pure.a) case impure: Freer.Impure[({type F[T] = Tell[W, T]})#F, A, B] => runAsList(impure.k(impure.fa.a)) match { case (ws, a) => (impure.fa.w :: ws, a) } } val e = for { _ <- tell("hoge") _ <- tell("fuga") } yield () runAsList(e) // (List(hoge, fuga),()) 8SJUFS͕'VODUPSͰͳͯ͘΋ɺ ϞφυʹͳΔ

Slide 32

Slide 32 text

'SFFS.BZCF type ConstUnit[A] = Unit type Maybe[A] = Freer[ConstUnit, A] def some[A](a: A): Maybe[A] = Pure[ConstUnit, A](a) def none[A]: Maybe[A] = Freer[ConstUnit, A]((): ConstUnit[Maybe[A]]) def safeDiv(n: Int, d: Int): Maybe[Int] = if (d == 0) none else some(n / d) val r = for { n <- safeDiv(4, 2) m <- safeDiv(n, 0) // none } yield m def maybe[A](maybe: Maybe[A])(default: A): A = maybe match { case Pure(a) => a case Impure((), _) => default } assert(maybe(r)(42) == 42) // r͕noneͳͷͰɺdefaultͷ42͕ద༻͞ΕΔ $POTU6OJU͕'VODUPSͰͳͯ͘΋ɺ ϞφυʹͳΔ

Slide 33

Slide 33 text

0QFO6OJPO 'SFFSͰఆٛͨ͠ϞφυΛ૊ΈΘͤΒΕͳ͍͔ʁ ܕͷ࿨Λ'SFFSʹ༩͑Δ cc 6OJPOΛ࢖ͬͨ'SFFS cc &YUFOTJCMF&⒎FDUT ྫ8SJUFS3FBEFS

Slide 34

Slide 34 text

0QFO6OJPO sealed trait Union // ܕͷऴ୺Λද͢ sealed trait Void extends Union // ܕͷ࿨Λߏ੒͢Δ sealed trait :+:[F[_], U <: Union] extends Union case class Inl[F[_], A, U <: Union](fa: F[A]) extends (F :+: U) // == :+:[F, U] case class Inr[F[_], U <: Union](u: U) extends (F :+: U) // == :+:[F, U] type ListOrOption = Option :+: List :+: Void val option1: ListOrOption = Inr(Inl(List(1, 2))) ܕͷ࿨Λ࣮ݱ͢Δ

Slide 35

Slide 35 text

.FNCFS trait Member[F[_], U <: Union] { // ϞφυΛߏ੒͢ΔF͔ΒUnionΛಘΔ def inject[A](f: F[A]): U } // ࠨଆ΁ͷຒΊࠐΈ implicit def left[F[_], U <: Union]: Member[F, F :+: U] = new Member[F, F :+: U] { def inject[A](f: F[A]): F :+: U = Inl(f) } // ӈଆ΁ͷຒΊࠐΈ implicit def right[F[_], G[_], U <: Union](implicit member: Member[F, U]): Member[F, G :+: U] = new Member[F, G :+: U] { def inject[A](f: F[A]): G :+: U = Inr(member.inject(f)) } 6OJPO΁஋ΛຒΊࠐΉͨΊͷܕΫϥε type ListOrOption = Option :+: List :+: Void val option1: ListOrOption = Inr(Inl(List(1, 2))) val option2: ListOrOption = Member[List, ListOrOption].inject(List(1, 2))

Slide 36

Slide 36 text

&YUFOTJCMF&⒎FDUT trait Eff[U <: Union, A] { def map[B](f: A => B): Eff[U, B] = flatMap(a => Pure(f(a))) def flatMap[B](f: A => Eff[U, B]): Eff[U, B] = this match { case Pure(a) => f(a) case Impure(u, g) => Impure(u, g :+ f) } } case class Pure[U <: Union, A](a: A) extends Eff[U, A] case class Impure[U <: Union, A, B](u: U, f: Arrows[U, A, B]) extends Eff[U, B] ܕύϥϝʔλʹ6OJPOΛ࣋ͭ

Slide 37

Slide 37 text

&⒎8SJUFS case class Writer[W](w: W) type U = Writer :+: Void implicit val w = Member[Writer, U] def tell[U <: Union, W] ( w: W)( implicit ev: Member[Writer, U]): Eff[U, Unit] = Eff.Impure(ev.inject(Writer(w)), Leaf((_: Any) => Eff.Pure(()))) def runWriter[U <: Union, W, A](eff: Eff[Writer :+: U, A]): Eff[U, (List[W], A)] = eff match { case Eff.Pure(a) => Eff.Pure((Nil, a)) case Eff.Impure(Inl(Writer(w: W)), k) => runWriter[U, W, A](k(w)) map { case (ws, a) => (w :: ws, a) } case Eff.Impure(Inr(r), k) => Eff.Impure(r, Leaf((a: Any) => runWriter(k(a)))) }

Slide 38

Slide 38 text

&⒎3FBEFS case class Reader[I]() type U = Reader :+: Void implicit val r = Member[Reader, U] def ask[U <: Union, I](implicit ev: Member[Reader, U]): Eff[U, I] = Eff.lift[U, Reader, I](Reader[I]) def runReader[U <: Union, I, A](eff: Eff[Reader :+: U, A], i: I): Eff[U, A] = eff match { case Eff.Pure(a) => Eff.Pure(a) case Eff.Impure(Inl(Reader()), k) => runReader(k(i), i) case Eff.Impure(Inr(r), k) => Eff.Impure(r, Leaf((a: Any) => runReader(k(a), i))) }

Slide 39

Slide 39 text

8SJUFS3FBEFS def run[A](eff: Eff[Void, A]): A = eff match { case Eff.Pure(a) => a } def e[U <: Union](implicit r: Member[Reader, U], w: Member[Writer, U]): Eff[U, Int] = for { _ <- Writer.tell(2) x <- Reader.ask[U, Int] _ <- Writer.tell(x + 1) } yield x type MonadStack = Reader :+: Writer :+: Void Eff.run(runWriter(runReader(e[MonadStack], 1))) // (List(2, 2),1)) ϞφυελοΫ ೋͭͷϞφυΛҰͭͷGPSࣜʹॻ͚Δ SVO3FBEFS SVO8SJUFS ҕৡ BTLϦΫΤετΛॲཧ UFMMϦΫΤετΛॲཧ QVSFͳܭࢉʹͳͬͨΒɺ SVOͰ݁ՌΛऔΓग़͢

Slide 40

Slide 40 text

&⒎͕ղܾ͢Δ͜ͱ ߹੒͢ΔϞφυ͕૿͑Δͨͼʹɺܭࢉͷޮ཰͕མͪΔ ԼҐͷϞφυͷॲཧΛߦ͏ͷʹɺҰʑMJGUΛߦ͏ඞཁ͕͋Δ Ϟφυͷ߹੒ॱ͸ݻఆ͞Ε͍ͯͯɺ్தͰೖΕସ͑Δ͜ͱ͕Ͱ͖ͳ͍ ϞφυΛ߹੒͢Δॱ൪ʹΑͬͯɺܭࢉͷҙຯ͕มΘΔ Ϟφυม׵ࢠͷ໰୊Λղܾ͢Δख๏

Slide 41

Slide 41 text

&⒎͕ղܾ͢Δ͜ͱ ߹੒͢ΔϞφυ͕૿͑Δͨͼʹɺܭࢉͷޮ཰͕མͪΔ ԼҐͷϞφυͷॲཧΛߦ͏ͷʹɺҰʑMJGUΛߦ͏ඞཁ͕͋Δ def e[U <: Union](implicit r: Member[Reader, U], w: Member[Writer, U]): Eff[U, Int] = for { _ <- Writer.tell(2) x <- Reader.ask[U, Int] _ <- Writer.tell(x + 1) } yield x ɾճϧʔϓ͕૸Βͳ͍ ɾMJGUΛߦ͏ඞཁ͕ͳ͍

Slide 42

Slide 42 text

&⒎͕ղܾ͢Δ͜ͱ def e[U <: Union](implicit r: Member[Reader, U], w: Member[Writer, U]): Eff[U, Int] = for { _ <- Writer.tell(2) x <- Reader.ask[U, Int] _ <- Writer.tell(x + 1) } yield x type MonadStack1 = Reader :+: Writer :+: Void type MonadStack2 = Writer :+: Reader :+: Void assert(Eff.run(runWriter(runReader(e[MonadStack1], 1))) == (List(2, 2),1)) assert(Eff.run(runReader(runWriter(e[MonadStack2]), 1)) == (List(2, 2),1)) Ϟφυͷ߹੒ॱ͸ݻఆ͞Ε͍ͯͯɺ్தͰೖΕସ͑Δ͜ͱ͕Ͱ͖ͳ͍ ϞφυΛ߹੒͢Δॱ൪ʹΑͬͯɺܭࢉͷҙຯ͕มΘΔ ݺͼग़͢ଆͰ੍ޚ͢Δ

Slide 43

Slide 43 text

6OJPO5ZQF val x: String | Int = if util.Random.nextBoolean() then "hoge" else 0 EPUUZͩͱ6OJPO5ZQF͕දݱ͠΍͍͢ <Ҿ༻IUUQTXXXTMJEFTIBSFOFU4BOTIJSP:PTIJEBFYUFOTJCMFF⒎FDUTJOEPUUZ>

Slide 44

Slide 44 text

&YUFOTJCMF&⒎FDUTJO%PUUZ val e: Eff[[T] => Reader[Int, T] | Writer[Int, T], Int] = for { x <- Reader.ask[Int] _ <- Writer.tell(x + 1) } yield x scala> run(runWriter(runReader(e, 0))) val res0: (Int, Int) = (1,0) ΑΓγϯϓϧͳهड़͕Մೳʹͳͬͨ def e[U <: Union](implicit r: Member[Reader, U], w: Member[Writer, U]) = ??? <Ҿ༻IUUQTXXXTMJEFTIBSFOFU4BOTIJSP:PTIJEBFYUFOTJCMFF⒎FDUTJOEPUUZ>

Slide 45

Slide 45 text

Benchmarks Ϟφυม׵ࢠͱ&⒎ͷϕϯνϚʔΫͷൺֱ͸ɺ ݩࢿྉʹࡌ͍ͬͯΔͷͰͦͪΒΛӾཡ͍ͩ͘͞ IUUQTXXXTMJEFTIBSFOFU4BOTIJSP:PTIJEBFYUFOTJCMFF⒎FDUTJOEPUUZ

Slide 46

Slide 46 text

·ͱΊ ɾϞφυελοΫ͸ɺϞφυม׵ࢠͷ໰୊Λղܾ͢Δ ɾ࣮૷͕ෳࡶɺɺ ɾ&YUFOTJCMF&⒎FDUT͸ϞφυΛҕৡؔ܎Ͱ දݱ͢Δ͜ͱʹΑͬͯɺϞφυελοΫΛ࣮ݱ͢Δ

Slide 47

Slide 47 text

ࢀߟจݙ IUUQTLPOOTBODPNQSPHIBTLFMMFYUFOTJCMFF⒎FDUTIUNM ˒ &YUFOTJCMF&⒎FDUT͸Ϟφυม׵ࢠʹର͢ΔٹੈओʹͳΓಘΔ͔ʁ IUUQIBMDBUPSHTDBMBFYUFOTJCMF ˒ &YUFOTJCMF&⒎FDUTJO4DBMB ˒ Freer Monads, More Extensible Effects IUUQTXXXTMJEFTIBSFOFULPOOGSFFSNPOBETNPSFFYUFOTJCMFF⒎FDUT