programs /** Apply the native function to the given arguments */ def native(name: String, args: Arg*): Program[REXP] = … def mean(x: Seq[Double]): Program[Double] = native("mean", x) flatMap toDouble def stdDev(x: Seq[Double]): Program[Double] = if (x.length < 2) const(0D) // < 2 datas will NaN else native("sd", x) flatMap toDouble
programs /** Apply the native function to the given arguments */ def native(name: String, args: Arg*): Program[REXP] = … def mean(x: Seq[Double]): Program[Double] = native("mean", x) flatMap toDouble def stdDev(x: Seq[Double]): Program[Double] = if (x.length < 2) const(0D) // < 2 datas will NaN else native("sd", x) flatMap toDouble def meanAndStdDev(values: Seq[Double]) : Program[(Double, Double, Int)] =
programs /** Apply the native function to the given arguments */ def native(name: String, args: Arg*): Program[REXP] = … def mean(x: Seq[Double]): Program[Double] = native("mean", x) flatMap toDouble def stdDev(x: Seq[Double]): Program[Double] = if (x.length < 2) const(0D) // < 2 datas will NaN else native("sd", x) flatMap toDouble def meanAndStdDev(values: Seq[Double]) : Program[(Double, Double, Int)] = for { m <- mean(values) sd <- stdDev(values) } yield (m, sd, values.length)
now what?
now what? • getting a value of type Program[A] is not the same as getting a value of type A, a program still needs to be executed.
now what? • getting a value of type Program[A] is not the same as getting a value of type A, a program still needs to be executed. • how do we execute a program?
now what? • getting a value of type Program[A] is not the same as getting a value of type A, a program still needs to be executed. • how do we execute a program? • first we need to compile it
compile
compile def compile[A](program: Program[A]): IO[A] =
compile def compile[A](program: Program[A]): IO[A] = IO {
compile def compile[A](program: Program[A]): IO[A] = IO { for { server <- Server.start()
compile def compile[A](program: Program[A]): IO[A] = IO { for { server <- Server.start() result <- try server execute program
compile def compile[A](program: Program[A]): IO[A] = IO { for { server <- Server.start() result <- try server execute program finally server.stop()
compile def compile[A](program: Program[A]): IO[A] = IO { for { server <- Server.start() result <- try server execute program finally server.stop() } yield result }
compile def compile[A](program: Program[A]): IO[A] = IO { for { server <- Server.start() result <- try server execute program finally server.stop() } yield result } def main(args: Array[String]) { batchedReduction.run.unsafePerformIO }
pooled
pooled def compilePooled[A](program: Program[A]): IO[A] =
pooled def compilePooled[A](program: Program[A]): IO[A] = IO {
pooled def compilePooled[A](program: Program[A]): IO[A] = IO { for { server <- pool.borrow
pooled def compilePooled[A](program: Program[A]): IO[A] = IO { for { server <- pool.borrow result <- try server execute program finally pool + server
pooled def compilePooled[A](program: Program[A]): IO[A] = IO { for { server <- pool.borrow result <- try server execute program finally pool + server } yield result }
problems
problems • error handling
problems • error handling • tail recursion/stack overflow
error handling
error handling sealed trait Invalid
error handling sealed trait Invalid case class Message(s: String) extends Invalid
error handling sealed trait Invalid case class Message(s: String) extends Invalid case class Err(x: Throwable) extends Invalid { … // define custom eq as Throwable doesn’t define eq }
error handling sealed trait Invalid case class Message(s: String) extends Invalid case class Err(x: Throwable) extends Invalid { … // define custom eq as Throwable doesn’t define eq } case class Composite(left: Invalid, right: Invalid) extends Invalid
Recommend
More recommend