monadic programmingのススメ - functional reactive programmingへのアプローチ

56
Monadic Programming のススメ Functional Reactive Programming へのアプローチ 2015421 Everforth 浅海智晴

Upload: tomoharu-asami

Post on 16-Jul-2015

3.142 views

Category:

Technology


2 download

TRANSCRIPT

  • Monadic Programming!Functional Reactive Programming2015421 Everforth

  • 1985() UNIX/OSWeb

    20019 Java, XML, UML

    2005420073

    () BusinessPlace () Everforth CTO

    UML(BP) ()

    http://www.apparel-cloud.com/ http://www.takumi-businessplace.co.jp/

  • ApparelCloud

    http://www.apparel-cloud.com/

  • ApparelCloud

  • ApparelCloud

    WebConsole

    Primefaces(JSF)

    WebAPI

    play

    PUSHSender

    playEmailSender

    play

    EverforthEngine

    play

    BatchEngine

    Shell

    AnalysisEngine

    Finagle

    StreamEngine

    Finagle

    ScalaJavaWeb

    iOS

    Android

    Web

    iOS

    Android

    CoordinationEngine

    ServiceMixCamel

  • Scala

    Object-Functional Analysis and Design

    Object-FunctionalProgramming

    Service Platform as-a-Service

    Cloud Service

    ModelSummay Model

    Apparel Cloud

    Service

    Regular Model

    WireFrame(+ Usage)

    Mindmap Model

    API Usage List

    Use case Model

    Domain Model

    ()

    ()

    Service Description

    : Everforth http://modegramming.blogspot.jp/2015/04/ofadeverforth.html

  • Monadic Programming

    Functional Reactive Programming

  • Monad Monadic Programming Functional Reactive Programming

  • SSD

    NoSQL CQRSEvent SourcingMicroservice

  • The Reactive Manifest http://www.reactivemanifesto.org/ http://okapies.hateblo.jp/entry/2014/12/03/025921

    Responsive

    Resilient

    Elastic

    Message Driven

    : Reactive Streams http://www.reactive-streams.org/

  • Reactive

    Service Cluster

    CPU Core

    Function

    Service

    Message

    Message

    Message

    Function

    Function

    Function

    Function

    Function

    Service

    Service

    Service

    Service

    Function

    Reactive

    Concurrent

    Parallel

    DistributedResponsive

    Resillience

    Elasticity

    Message Driven

    Concurrent

    Parallel

    Distributed

  • Functional Reactive Programming

    Object-Oriented Programming

    Actor

    Object-Oriented Programming

    Monadic Programming

    Functional Programming

    Object-Functional Programming

    Functional Reactive Programming

  • Hask

    ()

    Curry-Haward

  • Scala

    ScalaOOP (Java + )

    Functional Programming

    (Haskell )

    (e.g. Ruby)

    DSL

    (Scalable)

    Java VM

  • (semigroup) (monoid) (group)

    (associative law)

    ()

    (commutative law)

    (ring) (field)

    (distributive law)

    (a + b) + c = a + (b + c)

    a + b = b + a

    a * (b + c) = a * b + a * c

  • (category) Hask (Scala?) (kleisli category)

    (arrow, morphism)

    (functor)

    Applicative functor

    (monad)

  • (recursion) (high-order function) (immutable data) (lazy evaluation) (referential transparency) () (substitution model) (equational reasoning) (algebraic data type) , (direct product, direct sum) (persistent data structure) (effect) (type class) (monad)

    Object-Oriented Programming

    Monadic Programming

    Functional Programming

    Object-Functional Programming

    Functional Reactive Programming

  • Monadic Programming

  • Monads

    Eugenio Moggia program is an arrow of a Kleisli category(Kleisli triple)(Wikipedia)

    In functional programming, a monad is a structure that represents computations defined as sequences of steps: a type with a monad structure defines what it means to chain operations, or nest functions of that type together. This allows the programmer to build pipelines that process data in steps, in which each action is decorated with additional processing rules provided by the monad. (Wikipedia)

    ()

  • (Monadic)

    AB

    Functor

    Monad

    AM[B]

  • (List, Vector) (Option)

    Free, Operational

    DI(Dependency Injection) Reader

    State Process

    Slick Spark RDD(Resilient Distributed Dataset)

  • ()

    ()

    run

    IO

  • Option /

    List ()

    Vector ()

    Stream

    Try

    Future

  • State

    IO

    Process

  • Monadic Programming (Scalaz) Functor Applicative Functor Monad

    MonadApplicative FunctorFunctor MonadApplicative Functor

    Functor

  • Functor, Applicative Functor, Monad

    Functor

    Applicative Functor

    Monad

    F.point(x).map(f).map(g).map(h)

    (A.point(x) |@| A.point(y) |@| A.point(z))(i(_, _, _))

    f g h

    f

    f

    g

    g

    h

    h

    i

    x

    x

    y

    z

    M.point(x).flatMap(f).flatMap(g).flatMap(h)

    for { a

  • &Monad

    &Monad

    OOPAOPDI

  • Scalaz https://github.com/scalaz/scalaz : Scalaz: Type Classes and Pure Functional Data

    Structures for Scala : An extension to the core Scala library for functional

    programming. http://typelevel.org

    Scala HaskellScala

  • Monadic

    def validate(name: String, age: Int): ValidationNEL[Throwable, (String, Int)] = {! val a = validateName(name) ! val b = validateAge(age) ! if (a.isSuccess && b.isSuccess) { ! val a1 = a.asInstanceOf[Success[NonEmptyList[Throwable], String]].a ! val b1 = b.asInstanceOf[Success[NonEmptyList[Throwable], Int]].a ! Success((a1, b1)) ! } else if (a.isSuccess) { ! b.asInstanceOf[Failure[NonEmptyList[Throwable], (String, Int)]] ! } else if (b.isSuccess) { ! a.asInstanceOf[Failure[NonEmptyList[Throwable], (String, Int)]] ! } else { ! val a1 = a.asInstanceOf[Failure[NonEmptyList[Throwable], String]].e ! val b1 = b.asInstanceOf[Failure[NonEmptyList[Throwable], Int]].e ! Failure(a1 |+| b1) ! } !}!

    Java

  • def validate(name: String, age: Int): ValidationNEL[Throwable, (String, Int)] = { ! validateName(name) match { ! case Success(a) => validateAge(age) match { ! case Success(b) => Success((a, b)) ! case Failure(e) => Failure(e) ! } ! case Failure(e1) => validateAge(age) match { ! case Success(b) => Failure(e1) ! case Failure(e2) => Failure(e1 |+| e2) ! } ! } !} !

    def validate(name: String, age: Int): ValidationNEL[Throwable, (String, Int)] = { ! (validateName(name) validateAge(age))((_, _)) !}!

    Scala ()

    Scalaz (Monadic)

    : Scala Tips / Validation (10) - applicative http://modegramming.blogspot.jp/2012/04/scala-tips-validation-10-applicative.html

  • 3 calcString(x: Int): String calcInt(x: Int): Int calcFloat(x: Int): Float finalCalc(x: String, y: Int, z: Float): String

    Future

  • object Util { import java.net.URL import scala.concurrent.duration._ import scalax.io.JavaConverters._ def go[T](label: String)(body: => T) { val ts = System.currentTimeMillis val r = body val elapse = System.currentTimeMillis - ts println(s"$label ($elapse ms): $r") } def getPageLength(url: String): Int = { new URL(url).asInput.bytes.size }

    ScalaDSL go (bigCalc) { val r = bigCalc(1000) Await.result(r, 1.minute) }

  • def calcString(n: Int): String = { Thread.sleep(n) n.toString } def calcInt(n: Int): Int = { Thread.sleep(n) n } def calcFloat(n: Int): Float = { Thread.sleep(n) n.toFloat } def finalCalc(s: String, i: Int, f: Float): String = { s"$s-$i-$f" } }

  • def bigCalc(n: Int): String = { val a = calcString(n) val b = calcInt(n) val c = calcFloat(n) finalCalc(a, b, c) }

    bigCalc (3003 ms): 1000-1000-1000.0

    > go(bigCalc)(bigCalc(1000))

  • Option

    def bigCalcO(n: Int): Option[String] = { for { a

  • Option Monadic

    def calcStringO(n: Int): Option[String] = { Option(calcString(n)) } def calcIntO(n: Int): Option[Int] = { Option(calcInt(n)) } def calcFloatO(n: Int): Option[Float] = { Option(calcFloat(n)) } def bigCalcO2(n: Int): Option[String] = {

    for { a

  • Future val executorService = Executors.newFixedThreadPool(10) implicit val executionContext = ExecutionContext.fromExecutorService(executorService)

    def bigCalcP(n: Int): Future[String] = { for { a

  • Future def bigCalcP2(n: Int): Future[String] = { val fa = Future(calcString(n)) val fb = Future(calcInt(n)) val fc = Future(calcFloat(n)) for { a
  • Future Applicative

    def bigCalcP3(n: Int): Future[String] = { import scalaz._, Scalaz._ (Future(calcString(n)) |@| Future(calcInt(n)) |@| Future(calcFloat(n)))(finalCalc) } def bigCalcP31(n: Int): Future[String] = { import scalaz._, Scalaz._ ^^(Future(calcString(n)), Future(calcInt(n)), Future(calcFloat(n)))(finalCalc) }

    Applicative Functor

    f

    g

    h

    i

    x

    y

    z

    bigCalcP3 (1162 ms): 1000-1000-1000.0

    bigCalcP31 (1004 ms): 1000-1000-1000.0

    >go(bigCalcP3)(Await.result(bigCalcP3(1000), 1.minute))

    > go(bigCalcP31)(Await.result(bigCalcP31(1000), 1.minute))

    Applicative

  • Future Applicative

    def bigCalcA[A[_]](n: Int)(implicit C: Applicative[A]): A[String] = { ^^( C.point(calcString(n)), C.point(calcInt(n)), C.point(calcFloat(n)) )(finalCalc) }

    Applicative Functor

    f

    g

    h

    i

    x

    y

    z

    bigCalcAF (1003 ms): 1000-1000-1000.0

    bigCalcAI (3001 ms): 1000-1000-1000.0

    >go(bigCalcAF)(Await.result(bigCalcA[Future](1000), 1.minute))

    > go(bigCalcAI)(bigCalcA[Id](1000), 1.minute))

    Applicative

    Applicativepointvirtual constructor

    ()Applicative

  • Functional Reactive Programming

  • Reactive()

    Service Cluster

    CPU Core

    Function

    Service

    Message

    Message

    Message

    Function

    Function

    Function

    Function

    Function

    Service

    Service

    Service

    Service

    Function

    Reactive

    Concurrent

    Parallel

    DistributedResponsive

    Resillience

    Elasticity

    Message Driven

    Concurrent

    Parallel

    Distributed

  • Functional Reactive Programming /

    Callback hell

  • Functional Reactive Programming RxJava Scala https://github.com/ReactiveX/RxJava Observable

    Scalaz Stream https://github.com/scalaz/scalaz-stream Process

    Akka Stream https://typesafe.com/blog/typesafe-announces-akka-

    streams Akka actor

  • scalaz stream ScalazStreaming I/O https://github.com/scalaz/scalaz-stream

    Process

  • Process

    Function Function ProcessMonadProcessMonad

    Channel Sink

    Channel Sink

    Process Monad

  • 3 start

    : [scalaz-stream] http://modegramming.blogspot.jp/2015/03/scalaz-stream.html

  • case class Packet(seqno: Int, end: Boolean, content: String)

    def sink: Sink[Task, Packet] = { io.channel((a: Packet) => Task.delay(println(a))) }

    : [scalaz-stream] http://modegramming.blogspot.jp/2015/04/scalaz-stream.html

    : [scalaz-stream] Scala/OOP http://modegramming.blogspot.jp/2015/03/scalaoop.html

    : [scalaz-stream] Scala/FP http://modegramming.blogspot.jp/2015/03/scalafp.html

  • def buildTextToPacket[M[_]: Monad](source: Process[M, String]): Process[M, Packet] = { source. chunk(3). // 3 pipe(zipWithNext). // pipe(zipWithIndex). // map(toPacket) } def toPacket(x: ((Vector[String], Option[Vector[String]]), Int)): Packet = { val ((current, next), index) = x val content = current.mkString("-") val isend = next.cata(_.headOption === Some("start"), true) Packet(index + 1, isend, content) }

    - 3- - start

  • val source = io.linesR("data.txt") val pipeline = buildTextToPacket(source).to(sink) pipeline.run.run

    Packet(1,false,1-2-3) Packet(2,true,4-5-6) Packet(3,true,start-8-9)

    1 2 3 4 5 6 start 8 9

    chunk zipWithNextzipWithIndex toPacketChannel Sink

    Process Monad

  • EventProcessor

    val queue = EventProcessor.q val source = Vector("1", "2", "3", "4", "5", "6", "start", "8", "9") source foreach { x => queue.enqueueOne(x).run Thread.sleep(2000) }

    object EventProcessor { val q = async.unboundedQueue[String] val eventStream: Process[Task, String] = q.dequeue }

    : [scalaz-stream] http://modegramming.blogspot.jp/2015/04/scalaz-stream.html

  • val source = EventProcessor.eventStream val pipeline = buildTextToPacket(source).to(sink) pipeline.run.run

    Packet(1,false,1-2-3) Packet(2,true,4-5-6)

    chunk zipWithNextzipWithIndex toPacketChannel Sink

    Process Monad

  • DSL(Domain Specific Language)

    Monadic Programming

    Functional Reactive Programming Future Process

  • END