monadic programmingのススメ - functional reactive programmingへのアプローチ
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