SlideShare une entreprise Scribd logo
1  sur  74
Purely Functional I/O
Rúnar Bjarnason
@runarorama
QCon New York 2013

Thursday, June 13, 13
Watch the video with slide
synchronization on InfoQ.com!
http://www.infoq.com/presentations
/io-functional-side-effects

InfoQ.com: News & Community Site
• 750,000 unique visitors/month
• Published in 4 languages (English, Chinese, Japanese and Brazilian
Portuguese)
• Post content from our QCon conferences
• News 15-20 / week
• Articles 3-4 / week
• Presentations (videos) 12-15 / week
• Interviews 2-3 / week
• Books 1 / month
Presented at QCon New York
www.qconnewyork.com
Purpose of QCon
- to empower software development by facilitating the spread of
knowledge and innovation
Strategy
- practitioner-driven conference designed for YOU: influencers of
change and innovation in your teams
- speakers and topics driving the evolution and innovation
- connecting and catalyzing the influencers and innovators
Highlights
- attended by more than 12,000 delegates since 2007
- held in 9 cities worldwide
Who is this jackass?
•
•
•

Thursday, June 13, 13

Enterprise Java refugee

Author, Functional Programming in Scala
manning.com/bjarnason

Partially responsible for Scalaz and
Functional Java
What you should take
away from this talk
•
•
•

Thursday, June 13, 13

I/O can be done with pure functional
programming.
It really is purely functional.
How it’s done and why it’s done that way.
What is purely functional?

Thursday, June 13, 13
Functional programming is not
about lack of I/O

Thursday, June 13, 13
Functional programming is not
about first-class functions
or higher-order procedures.

Thursday, June 13, 13
Functional programming is not
about immutability.

Thursday, June 13, 13
Functional programming is
programming with pure functions

Thursday, June 13, 13
Functional programming is
programming with functions

Thursday, June 13, 13
A function of type (a → b) maps every value of type a
to exactly one value of type b.

(and nothing else)

Thursday, June 13, 13
No side-effects.

Thursday, June 13, 13
Side-effects
•
•
•
•
•
Thursday, June 13, 13

Reading from a file
Writing to the console
Starting threads
Throwing exceptions
Mutating memory
An expression e is referentially transparent if for all
programs p every occurrence of e in p can be replaced
with the result of evaluating e without changing the
meaning of p.

Thursday, June 13, 13
A function f is pure if f(x) is RT when x is RT.

Thursday, June 13, 13
A pure function always returns the same value
given the same input.

Thursday, June 13, 13
A pure function does not depend on anything
other than its argument.

Thursday, June 13, 13
The result of calling a pure function can be understood
completely by looking at the returned value.

Thursday, June 13, 13
x = 2
y = 4
p = x + y

Thursday, June 13, 13
y = 4
p = 2 + y

Thursday, June 13, 13
p = 2 + 4

Thursday, June 13, 13
p = 6

Thursday, June 13, 13
def x = new Date().getTime
def y = 4
def p = x + y

Thursday, June 13, 13
def y = 4
def p = 1369250684475 + y

Thursday, June 13, 13
A side-effect is anything that violates referential
transparency.

Thursday, June 13, 13
Problems with sideeffecting I/O
•
•
•
•
•
Thursday, June 13, 13

Any function can perform I/O
Monolithic, non-modular, limited reuse
Novel compositions difficult
Difficult to test
Difficult to scale
What we want
•
•
•
•

Thursday, June 13, 13

Clear separation of I/O concern
Modular and compositional API
Easy to test
Scales well
class Cafe {
def buyCoffee(cc: CreditCard): Coffee = {
val cup = new Coffee()
Payments.charge(cc, cup.price)
cup
}
}

Thursday, June 13, 13
class Cafe {
def buyCoffee(cc: CreditCard, p: Payments): Coffee = {
val cup = new Coffee()
p.charge(cc, cup.price)
cup
}
}

Thursday, June 13, 13
class Cafe {
def buyCoffee(cc: CreditCard): (Coffee, Charge) = {
val cup = new Coffee()
(cup, new Charge(cc, cup.price))
}
}

Thursday, June 13, 13
First-class I/O
Instead of performing I/O as a side-effect,
return a value to the caller that describes an
interaction with the external system.

Thursday, June 13, 13
Java

class App {
public static void main(String[] args) {}
}

Thursday, June 13, 13
Java

class App {
public static IO main(String[] args) {}
}

Thursday, June 13, 13
Haskell

main :: IO ()

Thursday, June 13, 13
Haskell

getLine :: IO String
putStrLn :: String -> IO ()

Thursday, June 13, 13
Haskell

getInt :: IO Int
getInt = fmap read getLine
fmap :: (a -> b) -> IO a -> IO b
read :: String -> Int

Thursday, June 13, 13
Haskell

echo = getLine >>= putStrLn
(>>=) :: IO a -> (a -> IO b) -> IO b

Thursday, June 13, 13
Haskell

cat = forever echo
forever x = x >> forever x
(>>) :: IO a -> IO b -> IO b

Thursday, June 13, 13
Haskell

cat = forever do
x <- getLine
putStrLn x
forever x = do { x; forever x }

Thursday, June 13, 13
Scala

println("What is your name?")
println("Hello, " + readLine)

Thursday, June 13, 13
Haskell

do
putStrLn "What is your name?"
putStrLn ("Hello, " ++ getLine)

Thursday, June 13, 13
Haskell
do

putStrLn "What is your name?"
putStrLn ("Hello, " ++ getLine)

Couldn't match expected type `String' with
actual type `IO String'
In the second argument of `(++)', namely
`getLine'

Thursday, June 13, 13
Haskell

putStrLn "What is your name?" >>
getLine >>= greet
greet name = putStrLn ("Hello, " ++ name)

Thursday, June 13, 13
Haskell

do
putStrLn "What is your name?"
name <- getLine
putStrLn ("Hello, " ++ name)

Thursday, June 13, 13
In Haskell, every program is
a single referentially transparent expression.

Thursday, June 13, 13
Benefits of IO
datatype
•
•
•

Thursday, June 13, 13

No side-effects. An IO action is a RT
description.
Effects are external to our program.
Action-manipulating functions!
Library of I/O
functions
sequence
mapM
replicateM
liftM2
forever
while

::
::
::
::
::
::

[IO a] -> IO [a]
(a -> IO b) -> [a] -> IO [b]
Int -> IO a -> IO [a]
(a -> b -> c) -> IO a -> IO b -> IO c
IO a -> IO b
IO Bool -> IO ()

And many more

Thursday, June 13, 13
Novel compositions

getTenLines :: IO [String]
getTenLines = sequence (replicate 10 getLine)

Thursday, June 13, 13
The world-as-state
model
class IO[A](val apply: RealWorld => (A, RealWorld))

Thursday, June 13, 13
The world-as-state
model
class IO[A](val apply: () => A)

Thursday, June 13, 13
The end of the world
sealed trait RealWorld
abstract class Program {
private val realWorld = new RealWorld {}
final def main(args: Array[String]): Unit =
pureMain(args).apply()
def pureMain(args: IndexedSeq[String]): IO[Unit]
}

Thursday, June 13, 13
Example IO actions
def io[A](a: => A): IO[A] =
new IO(() => a)
def putStrLn(s: String): IO[Unit] =
io(println(s))
def getLine: IO[String] =
io(readLine)

Thursday, June 13, 13
Composing actions

main = getLine >>= putStrLn >> main

Thursday, June 13, 13
Composing actions
class IO[A](val apply: () => A) {
def >>=[B](f: A => IO[B]): IO[B] = new IO[B](() => {
apply(rw)
f(a).apply(rw2)
})
def >>[B](b: => IO[B]): IO[B] = >>=(_ => b)
}

Thursday, June 13, 13
Composing actions
new Program {
def pureMain(args: IndexedSeq[String]): IO[Unit] =
(getLine >>= putStrLn) >> pureMain(args)
}

Thursday, June 13, 13
Composing actions
main = do
x <- getLine
putStrLn x
main

Thursday, June 13, 13
Composing actions
new Program {
def pureMain(args: IndexedSeq[String]): IO[Unit] =
for {
line <- getLine
_ <- putStrLn(line)
_ <- pureMain(args)
} yield ()
}

Thursday, June 13, 13
Composing actions
class IO[A](val apply: RealWorld => (A, RealWorld)) {
def >>=[B](f: A => IO[B]): IO[B] = new IO[B] { rw =>
val (a, rw2) = apply(rw)
f(a)
}
def >>[B](b: => IO[B]): IO[B] = >>=(_ => b)

}

Thursday, June 13, 13

def flatMap[B](f: A => IO[B]): IO[B] = >>=(f)
def map[B](f: A => B): IO[B] = >>=(a => io(f(a)))
Issues with
world-as-state
An IO[A] could do anything at all.

Thursday, June 13, 13
Issues with
world-as-state
This implementation overflows the stack in Scala.
Solved with trampolining.

Thursday, June 13, 13
Issues with
world-as-state
main = forever (getLine >>= putStrLn)
main = main

Thursday, June 13, 13
The “free monad”
model
sealed trait IO[A]
case class Pure[A](a: A) extends IO[A]
case class Request[I,A](
req: External[I],
k: I => IO[A]) extends IO[A]

Thursday, June 13, 13
The “free monad”
model
sealed trait IO[F[_],A]
case class Pure[F[_],A](a: A) extends IO[F,A]
case class Request[F[_],I,A](
req: F[I],
k: I => IO[A]) extends IO[A]

Thursday, June 13, 13
Any effect
trait Runnable[A] { def run: A }
def delay[A](a: => A) =
new Runnable[A] {
def run = a
}
type AnyIO[A] = IO[Runnable,A]

Thursday, June 13, 13
Console I/O
trait Console[A]
case object ReadLine extends Console[Option[String]]
case class PrintLn(s: String) extends Console[Unit]
type ConsoleIO[A] = IO[Console,A]

Thursday, June 13, 13
The end of the world
trait Run[F[_]] {
def apply[A](expr: F[A]): (A, Run[F])
}
abstract class App[F[_]](R: Run[F]) {
def main(a: Array[String]): IO[F,Unit] =
run(pureMain(a))
def pureMain(a: Array[String]): IO[F,Unit]

}
Thursday, June 13, 13

def run[A](io: IO[F,A]): A =
io match {
case Pure(a) => a
case Request(req, k) =>
val (e, r2) = R(expr)
run(r2)(k(e))
}
Console I/O
object RunConsole extends Run[Console] {
def apply[A](c: Console[A]) = c match {
case ReadLine => (Option(readLine), RunConsole)
case PrintLn(s) => (println(s), RunConsole)
}
}
IO.run(RunConsole): IO[Console,A] => A

Thursday, June 13, 13
We can use this same model for

•
•
•
•
•
•

Thursday, June 13, 13

file system access
network sockets
HTTP requests
JDBC actions
system clock access
non-blocking I/O
Summary
•
•
•

It really is purely functional.

•
Thursday, June 13, 13

I/O can be done with pure functional
programming.

Now you know how it’s done.

You don’t need a purely functional
language to do it.
Afterword
•
•
•
•
Thursday, June 13, 13

There’s a lot more to be said
This presentation is simplified
Streaming I/O
Mutable arrays and references
Chapter 13
Functional Programming
in Scala
manning.com/bjarnason

Thursday, June 13, 13
Questions?

Thursday, June 13, 13
Watch the video with slide synchronization on
InfoQ.com!
http://www.infoq.com/presentations/iofunctional-side-effects

Contenu connexe

Tendances

Kotlin Slides from Devoxx 2011
Kotlin Slides from Devoxx 2011Kotlin Slides from Devoxx 2011
Kotlin Slides from Devoxx 2011
Andrey Breslav
 

Tendances (6)

Idiomatic Kotlin
Idiomatic KotlinIdiomatic Kotlin
Idiomatic Kotlin
 
Kotlin Slides from Devoxx 2011
Kotlin Slides from Devoxx 2011Kotlin Slides from Devoxx 2011
Kotlin Slides from Devoxx 2011
 
Friendly Functional Programming
Friendly Functional ProgrammingFriendly Functional Programming
Friendly Functional Programming
 
Zio from Home
Zio from Home Zio from Home
Zio from Home
 
Fiber supervision in ZIO
Fiber supervision in ZIOFiber supervision in ZIO
Fiber supervision in ZIO
 
"That scripting language called Prolog"
"That scripting language called Prolog""That scripting language called Prolog"
"That scripting language called Prolog"
 

En vedette

Introduction to Functional Programming with Scala
Introduction to Functional Programming with ScalaIntroduction to Functional Programming with Scala
Introduction to Functional Programming with Scala
pramode_ce
 

En vedette (10)

Beyond Mere Actors
Beyond Mere ActorsBeyond Mere Actors
Beyond Mere Actors
 
Compositional I/O Stream in Scala
Compositional I/O Stream in ScalaCompositional I/O Stream in Scala
Compositional I/O Stream in Scala
 
Reasonable RPC with Remotely
Reasonable RPC with RemotelyReasonable RPC with Remotely
Reasonable RPC with Remotely
 
Peyton jones-2009-fun with-type_functions-slide
Peyton jones-2009-fun with-type_functions-slidePeyton jones-2009-fun with-type_functions-slide
Peyton jones-2009-fun with-type_functions-slide
 
Reactive Design Patterns
Reactive Design PatternsReactive Design Patterns
Reactive Design Patterns
 
Extending the Yahoo Streaming Benchmark + MapR Benchmarks
Extending the Yahoo Streaming Benchmark + MapR BenchmarksExtending the Yahoo Streaming Benchmark + MapR Benchmarks
Extending the Yahoo Streaming Benchmark + MapR Benchmarks
 
Why Play Framework is fast
Why Play Framework is fastWhy Play Framework is fast
Why Play Framework is fast
 
Livy: A REST Web Service For Apache Spark
Livy: A REST Web Service For Apache SparkLivy: A REST Web Service For Apache Spark
Livy: A REST Web Service For Apache Spark
 
The Columnar Era: Leveraging Parquet, Arrow and Kudu for High-Performance Ana...
The Columnar Era: Leveraging Parquet, Arrow and Kudu for High-Performance Ana...The Columnar Era: Leveraging Parquet, Arrow and Kudu for High-Performance Ana...
The Columnar Era: Leveraging Parquet, Arrow and Kudu for High-Performance Ana...
 
Introduction to Functional Programming with Scala
Introduction to Functional Programming with ScalaIntroduction to Functional Programming with Scala
Introduction to Functional Programming with Scala
 

Similaire à Purely Functional I/O

Towards a software ecosystem for java prolog interoperabilty
Towards a software ecosystem for java prolog interoperabiltyTowards a software ecosystem for java prolog interoperabilty
Towards a software ecosystem for java prolog interoperabilty
kim.mens
 
Introduction to Play 2
Introduction to Play 2Introduction to Play 2
Introduction to Play 2
Matteo Depalo
 

Similaire à Purely Functional I/O (20)

How to write better code: in-depth best practices for writing readable, simpl...
How to write better code: in-depth best practices for writing readable, simpl...How to write better code: in-depth best practices for writing readable, simpl...
How to write better code: in-depth best practices for writing readable, simpl...
 
How to write better code: in-depth best practices for writing readable, simpl...
How to write better code: in-depth best practices for writing readable, simpl...How to write better code: in-depth best practices for writing readable, simpl...
How to write better code: in-depth best practices for writing readable, simpl...
 
Clojure night
Clojure nightClojure night
Clojure night
 
EvoSoft 2013 Presentation
EvoSoft 2013 PresentationEvoSoft 2013 Presentation
EvoSoft 2013 Presentation
 
LogicObjects
LogicObjectsLogicObjects
LogicObjects
 
Issta13 workshop on debugging
Issta13 workshop on debuggingIssta13 workshop on debugging
Issta13 workshop on debugging
 
Towards a software ecosystem for java prolog interoperabilty
Towards a software ecosystem for java prolog interoperabiltyTowards a software ecosystem for java prolog interoperabilty
Towards a software ecosystem for java prolog interoperabilty
 
Ciconf 2012 - Better than Ad-hoc
Ciconf 2012 - Better than Ad-hocCiconf 2012 - Better than Ad-hoc
Ciconf 2012 - Better than Ad-hoc
 
Programação Funcional
Programação FuncionalProgramação Funcional
Programação Funcional
 
First Ride on Rust
First Ride on RustFirst Ride on Rust
First Ride on Rust
 
Java 8 new features or the ones you might actually use
Java 8 new features or the ones you might actually useJava 8 new features or the ones you might actually use
Java 8 new features or the ones you might actually use
 
Exploring Kotlin
Exploring KotlinExploring Kotlin
Exploring Kotlin
 
Functional Reactive Programming in Clojurescript
Functional Reactive Programming in ClojurescriptFunctional Reactive Programming in Clojurescript
Functional Reactive Programming in Clojurescript
 
What is this DI and AOP stuff anyway...
What is this DI and AOP stuff anyway...What is this DI and AOP stuff anyway...
What is this DI and AOP stuff anyway...
 
Having Fun with Kotlin Android - DILo Surabaya
Having Fun with Kotlin Android - DILo SurabayaHaving Fun with Kotlin Android - DILo Surabaya
Having Fun with Kotlin Android - DILo Surabaya
 
Introduction to Play 2
Introduction to Play 2Introduction to Play 2
Introduction to Play 2
 
Robot Localisation: An Introduction - Luis Contreras 2020.06.09 | RoboCup@Hom...
Robot Localisation: An Introduction - Luis Contreras 2020.06.09 | RoboCup@Hom...Robot Localisation: An Introduction - Luis Contreras 2020.06.09 | RoboCup@Hom...
Robot Localisation: An Introduction - Luis Contreras 2020.06.09 | RoboCup@Hom...
 
Functional programming
Functional programmingFunctional programming
Functional programming
 
The Not Java That's Not Scala
The Not Java That's Not ScalaThe Not Java That's Not Scala
The Not Java That's Not Scala
 
Design Patterns for Mobile Applications
Design Patterns for Mobile ApplicationsDesign Patterns for Mobile Applications
Design Patterns for Mobile Applications
 

Plus de C4Media

Plus de C4Media (20)

Streaming a Million Likes/Second: Real-Time Interactions on Live Video
Streaming a Million Likes/Second: Real-Time Interactions on Live VideoStreaming a Million Likes/Second: Real-Time Interactions on Live Video
Streaming a Million Likes/Second: Real-Time Interactions on Live Video
 
Next Generation Client APIs in Envoy Mobile
Next Generation Client APIs in Envoy MobileNext Generation Client APIs in Envoy Mobile
Next Generation Client APIs in Envoy Mobile
 
Software Teams and Teamwork Trends Report Q1 2020
Software Teams and Teamwork Trends Report Q1 2020Software Teams and Teamwork Trends Report Q1 2020
Software Teams and Teamwork Trends Report Q1 2020
 
Understand the Trade-offs Using Compilers for Java Applications
Understand the Trade-offs Using Compilers for Java ApplicationsUnderstand the Trade-offs Using Compilers for Java Applications
Understand the Trade-offs Using Compilers for Java Applications
 
Kafka Needs No Keeper
Kafka Needs No KeeperKafka Needs No Keeper
Kafka Needs No Keeper
 
High Performing Teams Act Like Owners
High Performing Teams Act Like OwnersHigh Performing Teams Act Like Owners
High Performing Teams Act Like Owners
 
Does Java Need Inline Types? What Project Valhalla Can Bring to Java
Does Java Need Inline Types? What Project Valhalla Can Bring to JavaDoes Java Need Inline Types? What Project Valhalla Can Bring to Java
Does Java Need Inline Types? What Project Valhalla Can Bring to Java
 
Service Meshes- The Ultimate Guide
Service Meshes- The Ultimate GuideService Meshes- The Ultimate Guide
Service Meshes- The Ultimate Guide
 
Shifting Left with Cloud Native CI/CD
Shifting Left with Cloud Native CI/CDShifting Left with Cloud Native CI/CD
Shifting Left with Cloud Native CI/CD
 
CI/CD for Machine Learning
CI/CD for Machine LearningCI/CD for Machine Learning
CI/CD for Machine Learning
 
Fault Tolerance at Speed
Fault Tolerance at SpeedFault Tolerance at Speed
Fault Tolerance at Speed
 
Architectures That Scale Deep - Regaining Control in Deep Systems
Architectures That Scale Deep - Regaining Control in Deep SystemsArchitectures That Scale Deep - Regaining Control in Deep Systems
Architectures That Scale Deep - Regaining Control in Deep Systems
 
ML in the Browser: Interactive Experiences with Tensorflow.js
ML in the Browser: Interactive Experiences with Tensorflow.jsML in the Browser: Interactive Experiences with Tensorflow.js
ML in the Browser: Interactive Experiences with Tensorflow.js
 
Build Your Own WebAssembly Compiler
Build Your Own WebAssembly CompilerBuild Your Own WebAssembly Compiler
Build Your Own WebAssembly Compiler
 
User & Device Identity for Microservices @ Netflix Scale
User & Device Identity for Microservices @ Netflix ScaleUser & Device Identity for Microservices @ Netflix Scale
User & Device Identity for Microservices @ Netflix Scale
 
Scaling Patterns for Netflix's Edge
Scaling Patterns for Netflix's EdgeScaling Patterns for Netflix's Edge
Scaling Patterns for Netflix's Edge
 
Make Your Electron App Feel at Home Everywhere
Make Your Electron App Feel at Home EverywhereMake Your Electron App Feel at Home Everywhere
Make Your Electron App Feel at Home Everywhere
 
The Talk You've Been Await-ing For
The Talk You've Been Await-ing ForThe Talk You've Been Await-ing For
The Talk You've Been Await-ing For
 
Future of Data Engineering
Future of Data EngineeringFuture of Data Engineering
Future of Data Engineering
 
Automated Testing for Terraform, Docker, Packer, Kubernetes, and More
Automated Testing for Terraform, Docker, Packer, Kubernetes, and MoreAutomated Testing for Terraform, Docker, Packer, Kubernetes, and More
Automated Testing for Terraform, Docker, Packer, Kubernetes, and More
 

Dernier

+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
?#DUbAI#??##{{(☎️+971_581248768%)**%*]'#abortion pills for sale in dubai@
 

Dernier (20)

Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
Manulife - Insurer Innovation Award 2024
Manulife - Insurer Innovation Award 2024Manulife - Insurer Innovation Award 2024
Manulife - Insurer Innovation Award 2024
 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...
Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...
Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
HTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesHTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation Strategies
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 

Purely Functional I/O

  • 1. Purely Functional I/O Rúnar Bjarnason @runarorama QCon New York 2013 Thursday, June 13, 13
  • 2. Watch the video with slide synchronization on InfoQ.com! http://www.infoq.com/presentations /io-functional-side-effects InfoQ.com: News & Community Site • 750,000 unique visitors/month • Published in 4 languages (English, Chinese, Japanese and Brazilian Portuguese) • Post content from our QCon conferences • News 15-20 / week • Articles 3-4 / week • Presentations (videos) 12-15 / week • Interviews 2-3 / week • Books 1 / month
  • 3. Presented at QCon New York www.qconnewyork.com Purpose of QCon - to empower software development by facilitating the spread of knowledge and innovation Strategy - practitioner-driven conference designed for YOU: influencers of change and innovation in your teams - speakers and topics driving the evolution and innovation - connecting and catalyzing the influencers and innovators Highlights - attended by more than 12,000 delegates since 2007 - held in 9 cities worldwide
  • 4. Who is this jackass? • • • Thursday, June 13, 13 Enterprise Java refugee Author, Functional Programming in Scala manning.com/bjarnason Partially responsible for Scalaz and Functional Java
  • 5. What you should take away from this talk • • • Thursday, June 13, 13 I/O can be done with pure functional programming. It really is purely functional. How it’s done and why it’s done that way.
  • 6. What is purely functional? Thursday, June 13, 13
  • 7. Functional programming is not about lack of I/O Thursday, June 13, 13
  • 8. Functional programming is not about first-class functions or higher-order procedures. Thursday, June 13, 13
  • 9. Functional programming is not about immutability. Thursday, June 13, 13
  • 10. Functional programming is programming with pure functions Thursday, June 13, 13
  • 11. Functional programming is programming with functions Thursday, June 13, 13
  • 12. A function of type (a → b) maps every value of type a to exactly one value of type b. (and nothing else) Thursday, June 13, 13
  • 14. Side-effects • • • • • Thursday, June 13, 13 Reading from a file Writing to the console Starting threads Throwing exceptions Mutating memory
  • 15. An expression e is referentially transparent if for all programs p every occurrence of e in p can be replaced with the result of evaluating e without changing the meaning of p. Thursday, June 13, 13
  • 16. A function f is pure if f(x) is RT when x is RT. Thursday, June 13, 13
  • 17. A pure function always returns the same value given the same input. Thursday, June 13, 13
  • 18. A pure function does not depend on anything other than its argument. Thursday, June 13, 13
  • 19. The result of calling a pure function can be understood completely by looking at the returned value. Thursday, June 13, 13
  • 20. x = 2 y = 4 p = x + y Thursday, June 13, 13
  • 21. y = 4 p = 2 + y Thursday, June 13, 13
  • 22. p = 2 + 4 Thursday, June 13, 13
  • 23. p = 6 Thursday, June 13, 13
  • 24. def x = new Date().getTime def y = 4 def p = x + y Thursday, June 13, 13
  • 25. def y = 4 def p = 1369250684475 + y Thursday, June 13, 13
  • 26. A side-effect is anything that violates referential transparency. Thursday, June 13, 13
  • 27. Problems with sideeffecting I/O • • • • • Thursday, June 13, 13 Any function can perform I/O Monolithic, non-modular, limited reuse Novel compositions difficult Difficult to test Difficult to scale
  • 28. What we want • • • • Thursday, June 13, 13 Clear separation of I/O concern Modular and compositional API Easy to test Scales well
  • 29. class Cafe { def buyCoffee(cc: CreditCard): Coffee = { val cup = new Coffee() Payments.charge(cc, cup.price) cup } } Thursday, June 13, 13
  • 30. class Cafe { def buyCoffee(cc: CreditCard, p: Payments): Coffee = { val cup = new Coffee() p.charge(cc, cup.price) cup } } Thursday, June 13, 13
  • 31. class Cafe { def buyCoffee(cc: CreditCard): (Coffee, Charge) = { val cup = new Coffee() (cup, new Charge(cc, cup.price)) } } Thursday, June 13, 13
  • 32. First-class I/O Instead of performing I/O as a side-effect, return a value to the caller that describes an interaction with the external system. Thursday, June 13, 13
  • 33. Java class App { public static void main(String[] args) {} } Thursday, June 13, 13
  • 34. Java class App { public static IO main(String[] args) {} } Thursday, June 13, 13
  • 35. Haskell main :: IO () Thursday, June 13, 13
  • 36. Haskell getLine :: IO String putStrLn :: String -> IO () Thursday, June 13, 13
  • 37. Haskell getInt :: IO Int getInt = fmap read getLine fmap :: (a -> b) -> IO a -> IO b read :: String -> Int Thursday, June 13, 13
  • 38. Haskell echo = getLine >>= putStrLn (>>=) :: IO a -> (a -> IO b) -> IO b Thursday, June 13, 13
  • 39. Haskell cat = forever echo forever x = x >> forever x (>>) :: IO a -> IO b -> IO b Thursday, June 13, 13
  • 40. Haskell cat = forever do x <- getLine putStrLn x forever x = do { x; forever x } Thursday, June 13, 13
  • 41. Scala println("What is your name?") println("Hello, " + readLine) Thursday, June 13, 13
  • 42. Haskell do putStrLn "What is your name?" putStrLn ("Hello, " ++ getLine) Thursday, June 13, 13
  • 43. Haskell do putStrLn "What is your name?" putStrLn ("Hello, " ++ getLine) Couldn't match expected type `String' with actual type `IO String' In the second argument of `(++)', namely `getLine' Thursday, June 13, 13
  • 44. Haskell putStrLn "What is your name?" >> getLine >>= greet greet name = putStrLn ("Hello, " ++ name) Thursday, June 13, 13
  • 45. Haskell do putStrLn "What is your name?" name <- getLine putStrLn ("Hello, " ++ name) Thursday, June 13, 13
  • 46. In Haskell, every program is a single referentially transparent expression. Thursday, June 13, 13
  • 47. Benefits of IO datatype • • • Thursday, June 13, 13 No side-effects. An IO action is a RT description. Effects are external to our program. Action-manipulating functions!
  • 48. Library of I/O functions sequence mapM replicateM liftM2 forever while :: :: :: :: :: :: [IO a] -> IO [a] (a -> IO b) -> [a] -> IO [b] Int -> IO a -> IO [a] (a -> b -> c) -> IO a -> IO b -> IO c IO a -> IO b IO Bool -> IO () And many more Thursday, June 13, 13
  • 49. Novel compositions getTenLines :: IO [String] getTenLines = sequence (replicate 10 getLine) Thursday, June 13, 13
  • 50. The world-as-state model class IO[A](val apply: RealWorld => (A, RealWorld)) Thursday, June 13, 13
  • 51. The world-as-state model class IO[A](val apply: () => A) Thursday, June 13, 13
  • 52. The end of the world sealed trait RealWorld abstract class Program { private val realWorld = new RealWorld {} final def main(args: Array[String]): Unit = pureMain(args).apply() def pureMain(args: IndexedSeq[String]): IO[Unit] } Thursday, June 13, 13
  • 53. Example IO actions def io[A](a: => A): IO[A] = new IO(() => a) def putStrLn(s: String): IO[Unit] = io(println(s)) def getLine: IO[String] = io(readLine) Thursday, June 13, 13
  • 54. Composing actions main = getLine >>= putStrLn >> main Thursday, June 13, 13
  • 55. Composing actions class IO[A](val apply: () => A) { def >>=[B](f: A => IO[B]): IO[B] = new IO[B](() => { apply(rw) f(a).apply(rw2) }) def >>[B](b: => IO[B]): IO[B] = >>=(_ => b) } Thursday, June 13, 13
  • 56. Composing actions new Program { def pureMain(args: IndexedSeq[String]): IO[Unit] = (getLine >>= putStrLn) >> pureMain(args) } Thursday, June 13, 13
  • 57. Composing actions main = do x <- getLine putStrLn x main Thursday, June 13, 13
  • 58. Composing actions new Program { def pureMain(args: IndexedSeq[String]): IO[Unit] = for { line <- getLine _ <- putStrLn(line) _ <- pureMain(args) } yield () } Thursday, June 13, 13
  • 59. Composing actions class IO[A](val apply: RealWorld => (A, RealWorld)) { def >>=[B](f: A => IO[B]): IO[B] = new IO[B] { rw => val (a, rw2) = apply(rw) f(a) } def >>[B](b: => IO[B]): IO[B] = >>=(_ => b) } Thursday, June 13, 13 def flatMap[B](f: A => IO[B]): IO[B] = >>=(f) def map[B](f: A => B): IO[B] = >>=(a => io(f(a)))
  • 60. Issues with world-as-state An IO[A] could do anything at all. Thursday, June 13, 13
  • 61. Issues with world-as-state This implementation overflows the stack in Scala. Solved with trampolining. Thursday, June 13, 13
  • 62. Issues with world-as-state main = forever (getLine >>= putStrLn) main = main Thursday, June 13, 13
  • 63. The “free monad” model sealed trait IO[A] case class Pure[A](a: A) extends IO[A] case class Request[I,A]( req: External[I], k: I => IO[A]) extends IO[A] Thursday, June 13, 13
  • 64. The “free monad” model sealed trait IO[F[_],A] case class Pure[F[_],A](a: A) extends IO[F,A] case class Request[F[_],I,A]( req: F[I], k: I => IO[A]) extends IO[A] Thursday, June 13, 13
  • 65. Any effect trait Runnable[A] { def run: A } def delay[A](a: => A) = new Runnable[A] { def run = a } type AnyIO[A] = IO[Runnable,A] Thursday, June 13, 13
  • 66. Console I/O trait Console[A] case object ReadLine extends Console[Option[String]] case class PrintLn(s: String) extends Console[Unit] type ConsoleIO[A] = IO[Console,A] Thursday, June 13, 13
  • 67. The end of the world trait Run[F[_]] { def apply[A](expr: F[A]): (A, Run[F]) } abstract class App[F[_]](R: Run[F]) { def main(a: Array[String]): IO[F,Unit] = run(pureMain(a)) def pureMain(a: Array[String]): IO[F,Unit] } Thursday, June 13, 13 def run[A](io: IO[F,A]): A = io match { case Pure(a) => a case Request(req, k) => val (e, r2) = R(expr) run(r2)(k(e)) }
  • 68. Console I/O object RunConsole extends Run[Console] { def apply[A](c: Console[A]) = c match { case ReadLine => (Option(readLine), RunConsole) case PrintLn(s) => (println(s), RunConsole) } } IO.run(RunConsole): IO[Console,A] => A Thursday, June 13, 13
  • 69. We can use this same model for • • • • • • Thursday, June 13, 13 file system access network sockets HTTP requests JDBC actions system clock access non-blocking I/O
  • 70. Summary • • • It really is purely functional. • Thursday, June 13, 13 I/O can be done with pure functional programming. Now you know how it’s done. You don’t need a purely functional language to do it.
  • 71. Afterword • • • • Thursday, June 13, 13 There’s a lot more to be said This presentation is simplified Streaming I/O Mutable arrays and references
  • 72. Chapter 13 Functional Programming in Scala manning.com/bjarnason Thursday, June 13, 13
  • 74. Watch the video with slide synchronization on InfoQ.com! http://www.infoq.com/presentations/iofunctional-side-effects