This presentation takes you on a functional programming journey, it starts from basic Scala programming language design concepts and leads to a concept of Monads, how some of them designed in Scala and what is the purpose of them
Function Programming in Scala.
A lot of my examples here comes from the book
Functional programming in Scala By Paul Chiusano and Rúnar Bjarnason, It is a good book, buy it.
Function Programming in Scala.
A lot of my examples here comes from the book
Functional programming in Scala By Paul Chiusano and Rúnar Bjarnason, It is a good book, buy it.
Function Programming in Scala.
A lot of my examples here comes from the book
Functional programming in Scala By Paul Chiusano and Rúnar Bjarnason, It is a good book, buy it.
Function Programming in Scala.
A lot of my examples here comes from the book
Functional programming in Scala By Paul Chiusano and Rúnar Bjarnason, It is a good book, buy it.
Function Programming in Scala.
A lot of my examples here comes from the book
Functional programming in Scala By Paul Chiusano and Rúnar Bjarnason, It is a good book, buy it.
Download for better quality.
Functor Composition - including (starting from) the definition in Bartosz Milewski's Category Theory book. https://github.com/hmemcpy/milewski-ctfp-pdf
Quicksort - a whistle-stop tour of the algorithm in five languages and four p...Philip Schwarz
Quicksort - a whistle-stop tour of the algorithm in five languages and four paradigms.
Programming Paradigms: Functional, Logic, Imperative, Imperative Functional
Languages: Haskell, Scala, Java, Clojure, Prolog
download for better quality - Learn about the sequence and traverse functions through the work of Runar Bjarnason and Paul Chiusano, authors of Functional Programming in Scala https://www.manning.com/books/functional-programming-in-scala, and Sam Halliday, author of "Functional Programming for Mortals with Scalaz" https://leanpub.com/fpmortals
Download for better quality.
Monads do not Compose. Not in a generic way - There is no general way of composing monads.
A comment from Rúnar Bjarnason, coauthor of FP in Scala: "They do compose in a different generic way. For any two monads F and G we can take the coproduct which is roughly Free of Either F or G (up to normalization)".
Another comment from Sergei Winitzki (which caused me to upload https://www.slideshare.net/pjschwarz/addendum-to-monads-do-not-compose): "It is a mistake to think that a traversable monad can be composed with another monad. It is true that, given `Traversable`, you can implement the monad's methods (pure and flatMap) for the composition with another monad (as in your slides 21 to 26), but this is a deceptive appearance. The laws of the `Traversable` typeclass are far insufficient to guarantee the laws of the resulting composed monad. The only traversable monads that work correctly are Option, Either, and Writer. It is true that you can implement the type signature of the `swap` function for any `Traversable` monad. However, the `swap` function for monads needs to satisfy very different and stronger laws than the `sequence` function from the `Traversable` type class. I'll have to look at the "Book of Monads"; but, if my memory serves, the FPiS book does not derive any of these laws." See https://www.linkedin.com/feed/update/urn:li:groupPost:41001-6523141414614814720?commentUrn=urn%3Ali%3Acomment%3A%28groupPost%3A41001-6523141414614814720%2C6532108273053761536%29
Inspired by Runar Bjarnason's scala exchange 2017 keynote https://skillsmatter.com/skillscasts/10746-keynote-composing-programs, I made a slide deck on Functor laws. Download for better quality.
N-Queens Combinatorial Problem - Polyglot FP for fun and profit - Haskell and...Philip Schwarz
Learn how to write FP code that displays a graphical representation of all the numerous N-Queens solutions for N=4,5,6,7,8 .
See how to neatly solve the problem by exploiting its self-similarity and using a divide and conquer approach.
Make light work of assembling multiple images into a whole, by exploiting Doodle’s facilities for combining images using a relative layout.
See relevant FP functions, like Foldable’s intercalate and intersperse, in action.
Code for part 3: https://github.com/philipschwarz/n-queens-combinatorial-problem-scala-part-3
Function Programming in Scala.
A lot of my examples here comes from the book
Functional programming in Scala By Paul Chiusano and Rúnar Bjarnason, It is a good book, buy it.
Function Programming in Scala.
A lot of my examples here comes from the book
Functional programming in Scala By Paul Chiusano and Rúnar Bjarnason, It is a good book, buy it.
Function Programming in Scala.
A lot of my examples here comes from the book
Functional programming in Scala By Paul Chiusano and Rúnar Bjarnason, It is a good book, buy it.
Download for better quality.
Functor Composition - including (starting from) the definition in Bartosz Milewski's Category Theory book. https://github.com/hmemcpy/milewski-ctfp-pdf
Quicksort - a whistle-stop tour of the algorithm in five languages and four p...Philip Schwarz
Quicksort - a whistle-stop tour of the algorithm in five languages and four paradigms.
Programming Paradigms: Functional, Logic, Imperative, Imperative Functional
Languages: Haskell, Scala, Java, Clojure, Prolog
download for better quality - Learn about the sequence and traverse functions through the work of Runar Bjarnason and Paul Chiusano, authors of Functional Programming in Scala https://www.manning.com/books/functional-programming-in-scala, and Sam Halliday, author of "Functional Programming for Mortals with Scalaz" https://leanpub.com/fpmortals
Download for better quality.
Monads do not Compose. Not in a generic way - There is no general way of composing monads.
A comment from Rúnar Bjarnason, coauthor of FP in Scala: "They do compose in a different generic way. For any two monads F and G we can take the coproduct which is roughly Free of Either F or G (up to normalization)".
Another comment from Sergei Winitzki (which caused me to upload https://www.slideshare.net/pjschwarz/addendum-to-monads-do-not-compose): "It is a mistake to think that a traversable monad can be composed with another monad. It is true that, given `Traversable`, you can implement the monad's methods (pure and flatMap) for the composition with another monad (as in your slides 21 to 26), but this is a deceptive appearance. The laws of the `Traversable` typeclass are far insufficient to guarantee the laws of the resulting composed monad. The only traversable monads that work correctly are Option, Either, and Writer. It is true that you can implement the type signature of the `swap` function for any `Traversable` monad. However, the `swap` function for monads needs to satisfy very different and stronger laws than the `sequence` function from the `Traversable` type class. I'll have to look at the "Book of Monads"; but, if my memory serves, the FPiS book does not derive any of these laws." See https://www.linkedin.com/feed/update/urn:li:groupPost:41001-6523141414614814720?commentUrn=urn%3Ali%3Acomment%3A%28groupPost%3A41001-6523141414614814720%2C6532108273053761536%29
Inspired by Runar Bjarnason's scala exchange 2017 keynote https://skillsmatter.com/skillscasts/10746-keynote-composing-programs, I made a slide deck on Functor laws. Download for better quality.
N-Queens Combinatorial Problem - Polyglot FP for fun and profit - Haskell and...Philip Schwarz
Learn how to write FP code that displays a graphical representation of all the numerous N-Queens solutions for N=4,5,6,7,8 .
See how to neatly solve the problem by exploiting its self-similarity and using a divide and conquer approach.
Make light work of assembling multiple images into a whole, by exploiting Doodle’s facilities for combining images using a relative layout.
See relevant FP functions, like Foldable’s intercalate and intersperse, in action.
Code for part 3: https://github.com/philipschwarz/n-queens-combinatorial-problem-scala-part-3
This 10 hours class is intended to give students the basis to empirically solve statistical problems. Talk 1 serves as an introduction to the statistical software R, and presents how to calculate basic measures such as mean, variance, correlation and gini index. Talk 2 shows how the central limit theorem and the law of the large numbers work empirically. Talk 3 presents the point estimate, the confidence interval and the hypothesis test for the most important parameters. Talk 4 introduces to the linear regression model and Talk 5 to the bootstrap world. Talk 5 also presents an easy example of a markov chains.
All the talks are supported by script codes, in R language.
Principles of functional progrmming in scalaehsoon
a short outline on necessity of functional programming and principles of functional programming in Scala.
In the article some keyword are used but not explained (to keep the article short and simple), the interested reader can look them up in internet.
Is it easier to add functional programming features to a query language, or to add query capabilities to a functional language? In Morel, we have done the latter.
Functional and query languages have much in common, and yet much to learn from each other. Functional languages have a rich type system that includes polymorphism and functions-as-values and Turing-complete expressiveness; query languages have optimization techniques that can make programs several orders of magnitude faster, and runtimes that can use thousands of nodes to execute queries over terabytes of data.
Morel is an implementation of Standard ML on the JVM, with language extensions to allow relational expressions. Its compiler can translate programs to relational algebra and, via Apache Calcite’s query optimizer, run those programs on relational backends.
In this talk, we describe the principles that drove Morel’s design, the problems that we had to solve in order to implement a hybrid functional/relational language, and how Morel can be applied to implement data-intensive systems.
(A talk given by Julian Hyde at Strange Loop 2021, St. Louis, MO, on October 1st, 2021.)
First Steps with Globus Compute Multi-User EndpointsGlobus
In this presentation we will share our experiences around getting started with the Globus Compute multi-user endpoint. Working with the Pharmacology group at the University of Auckland, we have previously written an application using Globus Compute that can offload computationally expensive steps in the researcher's workflows, which they wish to manage from their familiar Windows environments, onto the NeSI (New Zealand eScience Infrastructure) cluster. Some of the challenges we have encountered were that each researcher had to set up and manage their own single-user globus compute endpoint and that the workloads had varying resource requirements (CPUs, memory and wall time) between different runs. We hope that the multi-user endpoint will help to address these challenges and share an update on our progress here.
Cyaniclab : Software Development Agency Portfolio.pdfCyanic lab
CyanicLab, an offshore custom software development company based in Sweden,India, Finland, is your go-to partner for startup development and innovative web design solutions. Our expert team specializes in crafting cutting-edge software tailored to meet the unique needs of startups and established enterprises alike. From conceptualization to execution, we offer comprehensive services including web and mobile app development, UI/UX design, and ongoing software maintenance. Ready to elevate your business? Contact CyanicLab today and let us propel your vision to success with our top-notch IT solutions.
Developing Distributed High-performance Computing Capabilities of an Open Sci...Globus
COVID-19 had an unprecedented impact on scientific collaboration. The pandemic and its broad response from the scientific community has forged new relationships among public health practitioners, mathematical modelers, and scientific computing specialists, while revealing critical gaps in exploiting advanced computing systems to support urgent decision making. Informed by our team’s work in applying high-performance computing in support of public health decision makers during the COVID-19 pandemic, we present how Globus technologies are enabling the development of an open science platform for robust epidemic analysis, with the goal of collaborative, secure, distributed, on-demand, and fast time-to-solution analyses to support public health.
Unleash Unlimited Potential with One-Time Purchase
BoxLang is more than just a language; it's a community. By choosing a Visionary License, you're not just investing in your success, you're actively contributing to the ongoing development and support of BoxLang.
Into the Box Keynote Day 2: Unveiling amazing updates and announcements for modern CFML developers! Get ready for exciting releases and updates on Ortus tools and products. Stay tuned for cutting-edge innovations designed to boost your productivity.
Experience our free, in-depth three-part Tendenci Platform Corporate Membership Management workshop series! In Session 1 on May 14th, 2024, we began with an Introduction and Setup, mastering the configuration of your Corporate Membership Module settings to establish membership types, applications, and more. Then, on May 16th, 2024, in Session 2, we focused on binding individual members to a Corporate Membership and Corporate Reps, teaching you how to add individual members and assign Corporate Representatives to manage dues, renewals, and associated members. Finally, on May 28th, 2024, in Session 3, we covered questions and concerns, addressing any queries or issues you may have.
For more Tendenci AMS events, check out www.tendenci.com/events
Quarkus Hidden and Forbidden ExtensionsMax Andersen
Quarkus has a vast extension ecosystem and is known for its subsonic and subatomic feature set. Some of these features are not as well known, and some extensions are less talked about, but that does not make them less interesting - quite the opposite.
Come join this talk to see some tips and tricks for using Quarkus and some of the lesser known features, extensions and development techniques.
Understanding Globus Data Transfers with NetSageGlobus
NetSage is an open privacy-aware network measurement, analysis, and visualization service designed to help end-users visualize and reason about large data transfers. NetSage traditionally has used a combination of passive measurements, including SNMP and flow data, as well as active measurements, mainly perfSONAR, to provide longitudinal network performance data visualization. It has been deployed by dozens of networks world wide, and is supported domestically by the Engagement and Performance Operations Center (EPOC), NSF #2328479. We have recently expanded the NetSage data sources to include logs for Globus data transfers, following the same privacy-preserving approach as for Flow data. Using the logs for the Texas Advanced Computing Center (TACC) as an example, this talk will walk through several different example use cases that NetSage can answer, including: Who is using Globus to share data with my institution, and what kind of performance are they able to achieve? How many transfers has Globus supported for us? Which sites are we sharing the most data with, and how is that changing over time? How is my site using Globus to move data internally, and what kind of performance do we see for those transfers? What percentage of data transfers at my institution used Globus, and how did the overall data transfer performance compare to the Globus users?
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...Mind IT Systems
Healthcare providers often struggle with the complexities of chronic conditions and remote patient monitoring, as each patient requires personalized care and ongoing monitoring. Off-the-shelf solutions may not meet these diverse needs, leading to inefficiencies and gaps in care. It’s here, custom healthcare software offers a tailored solution, ensuring improved care and effectiveness.
May Marketo Masterclass, London MUG May 22 2024.pdfAdele Miller
Can't make Adobe Summit in Vegas? No sweat because the EMEA Marketo Engage Champions are coming to London to share their Summit sessions, insights and more!
This is a MUG with a twist you don't want to miss.
Accelerate Enterprise Software Engineering with PlatformlessWSO2
Key takeaways:
Challenges of building platforms and the benefits of platformless.
Key principles of platformless, including API-first, cloud-native middleware, platform engineering, and developer experience.
How Choreo enables the platformless experience.
How key concepts like application architecture, domain-driven design, zero trust, and cell-based architecture are inherently a part of Choreo.
Demo of an end-to-end app built and deployed on Choreo.
Enhancing Research Orchestration Capabilities at ORNL.pdfGlobus
Cross-facility research orchestration comes with ever-changing constraints regarding the availability and suitability of various compute and data resources. In short, a flexible data and processing fabric is needed to enable the dynamic redirection of data and compute tasks throughout the lifecycle of an experiment. In this talk, we illustrate how we easily leveraged Globus services to instrument the ACE research testbed at the Oak Ridge Leadership Computing Facility with flexible data and task orchestration capabilities.
Enterprise Resource Planning System includes various modules that reduce any business's workload. Additionally, it organizes the workflows, which drives towards enhancing productivity. Here are a detailed explanation of the ERP modules. Going through the points will help you understand how the software is changing the work dynamics.
To know more details here: https://blogs.nyggs.com/nyggs/enterprise-resource-planning-erp-system-modules/
Software Engineering, Software Consulting, Tech Lead.
Spring Boot, Spring Cloud, Spring Core, Spring JDBC, Spring Security,
Spring Transaction, Spring MVC,
Log4j, REST/SOAP WEB-SERVICES.
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...Globus
The U.S. Geological Survey (USGS) has made substantial investments in meeting evolving scientific, technical, and policy driven demands on storing, managing, and delivering data. As these demands continue to grow in complexity and scale, the USGS must continue to explore innovative solutions to improve its management, curation, sharing, delivering, and preservation approaches for large-scale research data. Supporting these needs, the USGS has partnered with the University of Chicago-Globus to research and develop advanced repository components and workflows leveraging its current investment in Globus. The primary outcome of this partnership includes the development of a prototype enterprise repository, driven by USGS Data Release requirements, through exploration and implementation of the entire suite of the Globus platform offerings, including Globus Flow, Globus Auth, Globus Transfer, and Globus Search. This presentation will provide insights into this research partnership, introduce the unique requirements and challenges being addressed and provide relevant project progress.
Enhancing Project Management Efficiency_ Leveraging AI Tools like ChatGPT.pdfJay Das
With the advent of artificial intelligence or AI tools, project management processes are undergoing a transformative shift. By using tools like ChatGPT, and Bard organizations can empower their leaders and managers to plan, execute, and monitor projects more effectively.
Large Language Models and the End of ProgrammingMatt Welsh
Talk by Matt Welsh at Craft Conference 2024 on the impact that Large Language Models will have on the future of software development. In this talk, I discuss the ways in which LLMs will impact the software industry, from replacing human software developers with AI, to replacing conventional software with models that perform reasoning, computation, and problem-solving.
2. Functions as Objects
What about functions?
In fact function values are treated as objects in Scala.
The function type A => B is just an abbreviation for the class
scala.Function1[A, B], which is defined as follows.
package scala
trait Function1[A, B] {
def apply(x: A): B
}
So functions are objects with apply methods.
3. Functions as Objects
An anonymous function such as
(x: Int) => x * x
is expanded to:
{
class AnonFun extends Function1[Int, Int] {
def apply(x: Int) = x * x
}
new AnonFun
}
or, shorter, using anonymous class syntax:
new Function1[Int, Int] {
def apply(x: Int) = x * x
}
4. Functions as Objects
A function call, such as f(a, b), where f is a value of some class
type, is expanded to
f.apply(a, b)
So the OO-translation of
val f = (x: Int) => x * x
f(7)
would be
val f = new Function1[Int, Int] {
def apply(x: Int) = x * x
}
f.apply(7)
5. Case Classes
A case class definition is similar to a normal class
definition, except that it is preceded by the
modifier case. For example:
trait Expr
case class Number(n: Int) extends Expr
case class Sum(e1: Expr, e2: Expr) extends Expr
Like before, this defines a trait Expr, and two
concrete subclasses
Number and Sum
6. Case Classes
It also implicitly defines companion objects with apply
methods.
object Number {
def apply(n: Int) = new Number(n)
}
object Sum {
def apply(e1: Expr, e2: Expr) = new Sum(e1, e2)
}
so you can write Number(1) instead of new Number(1).
7. Pattern matching
Pattern matching is a generalization of switch from C/Java to
class hierarchies.
It’s expressed in Scala using the keyword match.
Example
eval(Sum(Number(1), Number(2)))
def eval(e: Expr): Int = e match {
case Number(n) => n
case Sum(e1, e2) => eval(e1) + eval(e2)
}
8. Lists
The list is a fundamental data stucture in functional programming.
A list having x1, ...,xn as elements is written List(x1, ...,xn)
Example
val fruit = List(«apples», «oranges», «pears»)
val nums = List(1, 2, 3, 4)
val diag3 = List(List(1, 0, 0), List(0, 1, 0), List(0, 0, 1))
val empty = List()
There are two important differences between lists and arrays.
● List are imuttable - the elements of list cannot be changed
● Lists are recursive, while arrays are flat
9. Constructors of Lists
All lists are constructed from:
● The empty list Nil, and
● The constructor operation :: (pronounces cons):
x :: xs gives a new list with the first element x, followed
by the element of xs
Example
fruit = «apples» :: («oranges» :: («pears» :: Nil))
nums = 1 :: (2 :: (3 :: (4 :: Nil)))
empty = Nil
10. Map
A simple way to define map is as follows:
abstract class List[T] { ...
def map[U](f: T => U): List[U] = this match {
case Nil => Nil
case x :: xs => f(x) :: xs.map(f)
}
Example
def scaleList(xs: List[Double], factor: Double) =
xs map (x => x * factor)
11. flatMap
abstract class List[T] {
def flatMap[U](f: T => List[U]): List[U] = this match {
case x :: xs => f(x) ++ xs.flatMap(f)
case Nil => Nil
}
}
12. Filter
This pattern is generalized by the method filter of the List class:
abstract class List[T] {
...
def filter(p: T => Boolean): List[T] = this match {
case Nil => Nil
case x :: xs => if (p(x)) x :: xs.filter(p) else xs.filter(p)
}
}
Example
def posElems(xs: List[Int]): List[Int] =
xs filter (x => x > 0)
13. For-Expression
Higher-order functions such as map, flatMap
or filter provide powerful constructs for
manipulating lists.
But sometimes the level of abstraction
required by these function make the program
difficult to understand.
In this case, Scala's for expression notation
can help.
14. For-Expression Example
Let person be a list of elements of class Person, with fields
name and age.
case class Person(name: String, age: Int)
To obtain the names of person over 20 years old, you can
write:
for ( p <- persons if p.age > 20 ) yield p.name
Which is equivalent to:
persons filter (p => p.age > 20) map (p => p.name)
The for-expression is similar to loops in imperative languages,
except that is builds a list of the result of all iterations.
15. Syntax of For
A for-expression is of the form:
for ( s ) yield e
where s is a sequence of generators and filters, and e is an expression whose value is
returned by an iteration.
●
A generator is of the form p <- e, where p is a pattern and e an expression whose value is a
collection.
●
A filter is of the form if f where f is a boolean expression.
●
The sequence must start with generator.
●
If there are several generators in the sequence, the last generators vary faster than the first.
Example
for {
i <- 1 until n
j <- 1 until i
if isPrime(i + j)
} yield (i, j)
16. Queries with for
case class Book(title: String, authors: List[String])
val books: List[Book] = List(
Book(title = ”Structure and Interpretation of Computer Programs”,
authors = List(”Abelson, Harald”, ”Sussman, Gerald J.”)),
Book(title = ”Introduction to Functional Programming”,
authors = List(”Bird, Richard”, ”Wadler, Phil”)),
Book(title = ”Effective Java”,
authors = List(”Bloch, Joshua”)),
Book(title = ”Java Puzzlers”,
authors = List(”Bloch, Joshua”, ”Gafter, Neal”)),
Book(title = ”Programming in Scala”,
authors = List(”Odersky, Martin”, ”Spoon, Lex”, ”Venners, Bill”)))
To find the names of all authors who have written at least two books present in the database:
for {
b1 <- books
b2 <- books
if b1.title < b2.title
a1 <- b1.authors
a2 <- b2.authors
if a1 == a2
} yield a1
17. For-Expressions and Higher-Order
Functions
The syntax of for is closely related to the higher-order
functions map, flatMap and filter.
First of all, these functions can all be defined in terms of for:
def map[T, U](xs: List[T], f: T => U): List[U] =
for (x <- xs) yield f(x)
def flatMap[T, U](xs: List[T], f: T => Iterable[U]): List[U] =
for (x <- xs; y <- f(x)) yield y
def filter[T](xs: List[T], p: T => Boolean): List[T] =
for (x <- xs if p(x)) yield x
And vice versa
18. Translation of For
In reality, the Scala compiler expresses for-
expression in terms of map, flatMap and a lazy
variant of filter.
1. A simple for expression
for (x <- e1) yield e2
is translated to
e1.map(x => e2)
19. Translation of For
2: A for-expression
for (x <- e1 if f; s) yield e2
where f is a filter and s is a (potentially empty)
sequence of generators and filters, is translated to
for (x <- e1.withFilter(x => f); s) yield e2
(and the translation continues with the new expression)
You can think of withFilter as a variant of filter that
does not produce an intermediate list, but instead
filters the following map or flatMap function application.
20. Translation of For
3: A for-expression
for (x <- e1; y <- e2; s) yield e3
where s is a (potentially empty) sequence of
generators and filters,
is translated into
e1.flatMap(x => for (y <- e2; s) yield e3)
(and the translation continues with the new
expression)
21. Example
Take the for-expression that computed pairs whose sum is
prime:
for {
i <- 1 until n
j <- 1 until i
if isPrime(i + j)
} yield (i, j)
Applying the translation scheme to this expression gives:
(1 until n).flatMap(i =>
(1 until i).withFilter(j => isPrime(i+j))
.map(j => (i, j)))
22. For and Databases
For example, books might not be a list, but a database stored on
some server.
As long as the client interface to the database defines the methods
map, flatMap and withFilter, we can use the for syntax for querying
the database.
This is the basis of the Scala data base connection frameworks
ScalaQuery and Slick.
Similar ideas underly Microsoft’s LINQ(for (c < -coffees;
if c.sales > 999
)yield c.nam e).run
select"CO F_NAM E"
from "CO FFEES"
w here "SALES" > 999
23. Coffee break
As soon as you understand Monads, you will understand that
this is a Monad, too.
{{alt: What if someone broke out of a hypothetical situation in
your room right now?}}
24. Monads
Data structures with map and flatMap seem to
be quite common.
In fact there’s a name that describes this class
of a data structures together with some
algebraic laws that they should have.
They are called monads.
25. What is a Monad?
A monad M is a parametric type M[T] with two
operations, flatMap and unit, that have to satisfy
some laws.
trait M[T] {
def flatMap[U](f: T => M[U]): M[U]
}
def unit[T](x: T): M[T]
In the literature, flatMap is more commonly
called bind.
26. Examples of Monads
– List is a monad with unit(x) = List(x)
– Set is monad with unit(x) = Set(x)
– Option is a monad with unit(x) = Some(x)
– Generator is a monad with unit(x) = single(x)
– …......
flatMap is an operation on each of these
types, whereas unit in Scala is di erent forff
each monad.
27. Monads and map
map can be defined for every monad as a
combination of flatMap and unit:
m map f
== m flatMap (x => unit(f(x)))
== m flatMap (f andThen unit)
28. Monad Laws
To qualify as a monad, a type has to satisfy
three laws:
Associativity
m flatMap f flatMap g == m flatMap (x => f(x) flatMap g)
Left unit
unit(x) flatMap f == f(x)
Right unit
m flatMap unit == m
29. The Option monad
sealed trait Option[A] {
def map[B](f: A => B): Option[B]
def flatMap[B](f: A => Option[B]): Option[B]
}
case class Some[A](a: A) extends Option[A]
case class None[A] extends Option[A]
The Option monad makes the possibility of
missing data explicit in the type system, while
hiding the boilerplate «if non-null» logic
30. Checking Monad Laws
Let’s check the monad laws for Option.
Here’s flatMap for Option:
abstract class Option[+T] {
def flatMap[U](f: T => Option[U]): Option[U] = this match
{
case Some(x) => f(x)
case None => None
}
}
31. Try
Try resembles Option, but instead of Some/None
there is a Success case with a value and a Failure
case that contains an exception:
abstract class Try[+T]
case class Success[T](x: T) extends Try[T]
case class Failure(ex: Exception) extends Try[Nothing]
Try is used to pass results of computations that
can fail with an exception between threads and
computers
32. Creating a Try
You can wrap up an arbitrary computation in a Try.
Try(expr) // gives Success(someValue) or Failure(someException)
Here’s an implementation of Try:
object Try {
def apply[T](expr: => T): Try[T] =
try Success(expr)
catch {
case NonFatal(ex) => Failure(ex)
}
}
33. Composing Try
Just like with Option, Try-valued computations can be composed
in for
expresssions.
for {
x <- computeX
y <- computeY
} yield f(x, y)
If computeX and computeY succeed with results Success(x) and
Success(y), this will return Success(f(x, y)).
If either computation fails with an exception ex, this will return
Failure(ex).
34. Definition of flatMap and map on Try
abstract class Try[T] {
def flatMap[U](f: T => Try[U]): Try[U] = this match {
case Success(x) => try f(x) catch { case NonFatal(ex) => Failure(ex) }
case fail: Failure => fail
}
def map[U](f: T => U): Try[U] = this match {
case Success(x) => Try(f(x))
case fail: Failure => fail
}
}
The Try monad makes the possibility of errors explicit in
the type system, while hiding the boilerplate «try/catch»
logic
35. We have seen that for-expressions are useful not only for collections. Many other types
also define map,flatMap, and withFilter operations and with them for-expressions.
Examples: Generator, Option, Try.
Many of the types defining flatMap are monads.
(If they also define withFilter, they are called “monads with zero”).
The three monad laws give useful guidance in the design of library APIs.
36. Reactive manifesto
[Merriam Webster] reactive: “readily responsive to a stimulus”.
▶ React to events (event-driven)
▶ React to load (scalable)
▶ React to failures (resilient)
▶ React to users (responsive)
37. Lets play a simple game:
trait Adventure {
def collectCoins(): List[Coin]
def buyTreasure(coins: List[Coin]): Treasure
}
val adventure = Adventure()
val coins = adventure.collectCoins()
val treasure = adventure.buyTreasure(coins)
38. Actions may fail
def collectCoins(): List[Coin] = {
if (eatenByMonster(this))
throw new GameOverException(“Ooops”)
List(Gold, Gold, Silver)
}
def buyTreasure(coins: List[Coin]): Treasure = {
if (coins.sumBy(_.value) < treasureCost)
throw new GameOverException(“Nice try!”)
Diamond
}
val adventure = Adventure()
val coins = adventure.collectCoins()
val treasure = adventure.buyTreasure(coins)
39. Sequential composition of actions
that may fail
val adventure = Adventure()
val coins = adventure.collectCoins()
// block until coins are collected
// only continue if there is no exception
val treasure = adventure.buyTreasure(coins)
// block until treasure is bought
// only continue if there is no exception
41. Making failure evident intypes
import scala.util.{Try, Success, Failure}
abstract class Try[T]
case class Success[T](elem: T) extends Try[T]
case class Failure(t: Throwable) extends Try[Nothing]
object Try {
def apply[T](r: =>T): Try[T] = {
try { Success(r) }
catch { case t => Failure(t) }
}
trait Adventure {
def collectCoins(): Try[List[Coin]]
def buyTreasure(coins: List[Coin]): Try[Treasure]
}
42. Dealing with failure explicitly
val adventure = Adventure()
val coins: Try[List[Coin]] = adventure.collectCoins()
val treasure: Try[Treasure] = coins match {
case Success(cs) adventure.buyTreasure(cs)⇒
case failure @ Failure(t) failure⇒
}
43. Noise reduction
val adventure = Adventure()
val treasure: Try[Treasure] =
adventure.collectCoins().flatMap(coins {⇒
adventure.buyTreasure(coins)
})
val treasure: Try[Treasure] = for {
coins <- adventure.collectCoins()
treasure <- buyTreasure(coins)
} yield treasure
44. Amonad that handles exceptions.
Try[T]
The Try monad makes the possibility of errors
explicit in the type system, while hiding the
boilerplate «try/catch» logic
45. trait Socket {
def readFromMemory(): Array[Byte]
def sendToEurope(packet: Array[Byte]): Array[Byte]
}
val socket = Socket()
val packet = socket.readFromMemory()
val confirmation = socket.sendToEurope(packet)
47. val socket = Socket()
val packet = socket.readFromMemory()
// block for 50,000 ns
// only continue if there is no exception
val confirmation = socket.sendToEurope(packet)
// block for 150,000,000 ns
// only continue if there is no exception
Lets translate this into human terms. 1 nanosecond → 1 second
val socket = Socket()
val packet = socket.readFromMemory()
// block for 3 days
// only continue if there is no exception
val confirmation = socket.sendToEurope(packet)
// block for 5 years
// only continue if there is no exception
48. Futures asynchronously notify
consumers
Future[T]
A monad that handles
exceptions and latency
import scala.concurrent._
import scala.concurrent.ExecutionContext.Implicits.global
trait Future[T] {
def onComplete(callback: Try[T] Unit)⇒
(implicit executor: ExecutionContext): Unit
}
50. Sendpackets using futures
val socket = Socket()
val packet: Future[Array[Byte]] =
socket.readFromMemory()
packet onComplete {
case Success(p) {⇒
val confirmation: Future[Array[Byte]] =
socket.sendToEurope(p)
}
case Failure(t) => …
}
51. Creating Futures
// Starts an asynchronous computation
// and returns a future object to which you
// can subscribe to be notified when the
// future completes
object Future {
def apply(body: T)⇒
(implicit context: ExecutionContext): Future[T]
}
52. Creating Futures
import scala.concurrent.ExecutionContext.Implicits.global
import akka.serializer._
val memory = Queue[EMailMessage](
EMailMessage(from = “Erik”, to = “Roland”),
EMailMessage(from = “Martin”, to = “Erik”),
EMailMessage(from = “Roland”, to = “Martin”))
def readFromMemory(): Future[Array[Byte]] = Future {
val email = queue.dequeue()
val serializer = serialization.findSerializerFor(email)
serializer.toBinary(email)
}
53. Some Other Useful Monads
● The List monad makes nondeterminism explicit in the type
system, while hiding the boilerplate of nested for-loops.
● The Promise monad makes asynchronous computation
explicit in the type system, while hiding the boilerplate of
threading logic
● The Transaction monad (non-standard) makes
transactionality explicit in the type system, while hiding the
boilerplate of invoking rollbacks
● … and more. Use monads wherever possible to keep your
code clean!
54. Future[T] and Try[T] are dual
trait Future[T] {
def OnComplete[U](func: Try[T] U)⇒
(implicit ex: ExecutionContext): Unit
}
Lets simplify:
(Try[T] Unit) Unit⇒ ⇒
55. Future[T] and Try[T] are dual
(Try[T] Unit) Unit⇒ ⇒
Reverse:
Unit (Unit Try[T])⇒ ⇒
Simplify:
() (() Try[T])⇒ ⇒ ≈ Try[T]
56. Future[T] and Try[T] are dual
Receive result of type Try[T] by passing
callback (Try[T] Unit)⇒ to method
def asynchronous(): Future[T] = { … }
Receive result of type Try[T] by blocking
until method returns
def synchronous(): Try[T] = { … }