0% found this document useful (0 votes)
2 views25 pages

Lecture 9

The lecture discusses the transition from imperative programming with side effects to pure functional programming, emphasizing the importance of pure functions that do not alter state or produce side effects. It introduces concepts such as referential transparency, explicit state transitions, and combinators for managing state in a functional manner. The lecture also highlights the use of random number generators (RNG) as an example of how to implement stateful computations without side effects.

Uploaded by

moh570kamil
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views25 pages

Lecture 9

The lecture discusses the transition from imperative programming with side effects to pure functional programming, emphasizing the importance of pure functions that do not alter state or produce side effects. It introduces concepts such as referential transparency, explicit state transitions, and combinators for managing state in a functional manner. The lecture also highlights the use of random number generators (RNG) as an example of how to implement stateful computations without side effects.

Uploaded by

moh570kamil
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 25

CS 474: Object-Oriented Languages and

Environments
Lecture 9: Onward From Imperative Programming
with Side-Effects to Pure Functional Programming.

Instructor: Dr. Mark Grechanik


University of Illinois at Chicago
Modeling/Coding Coffee Purchases

Department of Computer Science, the


University of Illinois at Chicago 2
Side Effects

n Charging a credit card involves some


interaction with the outside world—suppose it
requires contacting the credit card company
via some web service, authorizing the
transaction, charging the card, and (if
successful) persisting some record of the
transaction for later reference.
n But our function merely returns a Coffee and
these other actions are happening on the
side, hence the term “side effect.
Department of Computer Science, the
University of Illinois at Chicago 3
Side Effects of Side Effects

n As a result of this side effect, the code is


difficult to test.
q We don’t want our tests to actually contact the
credit card company and charge the card!
n CreditCard shouldn’t have any knowledge
baked into it about how to contact the credit
card company to actually execute a charge,
nor should it have knowledge of how to
persist a record of this charge in our internal
systems!
Department of Computer Science, the
University of Illinois at Chicago 4
Department of Computer Science, the
University of Illinois at Chicago 5
Remove Side Effects

Department of Computer Science, the


University of Illinois at Chicago 6
More Improvements

Department of Computer Science, the


University of Illinois at Chicago 7
Pure Functions

n A function f with input type A and output type B


(written in Scala as a single type: A => B,
pronounced “A to B” or “A arrow B”) is a
computation that relates every value a of type A
to exactly one value b of type B such that b is
determined solely by the value of a.
n Any changing state of an internal or external
process is irrelevant to computing the result f(a).
q For example, a function intToString having type Int =>
String will take every integer to a corresponding string.
Department of Computer Science, the
University of Illinois at Chicago 8
Pure Functions and Side Effects

n If a function has no observable effect on the


execution of the program other than to
compute a result given its inputs then it has
no side effects.

n We sometimes qualify such functions as pure


functions to make this more explicit.
n Unless we state otherwise, we’ll often use
function to imply no side effects.
Department of Computer Science, the
University of Illinois at Chicago 9
Purity And Referential Transparency
n An expression e is referentially transparent if, for all
programs p, all occurrences of e in p can be replaced by
the result of evaluating e without affecting the meaning
of p.
n A function f is pure if the expression f(x) is referentially
transparent for all referentially transparent x.
def buyCoffee(cc: CreditCard): Coffee =
{
val cup = new Coffee()
cc.charge(cup.price)
cup
}
Department of Computer Science, the
University of Illinois at Chicago 10
PFD of Random Number Generator

n What is the internal state of an RNG?


n Are these state updates RT?

Department of Computer Science, the


University of Illinois at Chicago 11
How to Test This RNG?

n Tests should be reproducible.


n Every time we call nextInt, the previous state
of the random number generator is destroyed.
n What about testing RNG’s usage in the
context of some application?

Department of Computer Science, the


University of Illinois at Chicago 12
Core Functional Design Idea

n Make the state updates explicit!


n Don’t update the state as a side effect, but
simply return the new state along with the
value that we’re generating.

trait RNG {
def nextInt: (Int, RNG)
}
Department of Computer Science, the
University of Illinois at Chicago 13
Separation of Concerns

n We separate the concern of computing what the


next state is from the concern of communicating
the new state to the rest of the program.
n No global mutable memory is being used—we
simply return the next state back to the caller.
n This leaves the caller of nextInt in complete
control of what to do with the new state.
n We’re still encapsulating the state, in the sense
that users of this API don’t know anything about
the implementation of the RNG itself.
Department of Computer Science, the
University of Illinois at Chicago 14
Department of Computer Science, the
University of Illinois at Chicago 15
Time to Implement the RNG
n A linear congruential generator (LCG) is an
algorithm that yields a sequence of pseudo-
randomized numbers calculated with a
discontinuous piecewise linear equation.
https://en.wikipedia.org/wiki/Linear_congruent
ial_generator

Department of Computer Science, the


University of Illinois at Chicago 16
Using RNG

n We can run this sequence of statements as


many times as we want and we’ll always get
the same values.

Department of Computer Science, the


University of Illinois at Chicago 17
Explicit Transitions From State 2 State

n class Foo { private var s: FooState = ...


def bar: Bar
def baz: Int
}
n trait Foo {
def bar: (Bar, Foo)
def baz: (Int, Foo)
}
n The caller is responsible for passing the computed
next state through the rest of the program.
Department of Computer Science, the
University of Illinois at Chicago 18
Extending the RNG

n If we want to generate two distinct numbers,


we need to use the RNG returned by the first
call to nextInt to generate the second Int.

n Do you see a new programming pattern?


n RNG => (A, RNG)
Department of Computer Science, the
University of Illinois at Chicago 19
type Rand[+A] = RNG => (A, RNG)
n Functions of this type are called state actions
or state transitions because they transform
RNG states from one to the next.
n These state actions can be combined using
combinators, which are higher-order
functions.
n A state action is a program that depends on
some RNG, uses it to generate an A, and
also transitions the RNG to a new state that
can be used by another action later.
Department of Computer Science, the
University of Illinois at Chicago 20
Combinators

n Combinators are functions that let us


combine Rand actions while avoiding
explicitly passing along the RNG state.
n A simple RNG state transition is the unit
action, which passes the RNG state through
without using it, always returning a constant
value rather than a random value:
def unit[A](a: A): Rand[A] = rng => (a, rng)
n Can we generalize it?
Department of Computer Science, the
University of Illinois at Chicago 21
Combinator map

n We need a combinator for transforming the


output of a state action without modifying the
state itself.
n Remember, Rand[A] is just a type alias for a
function type RNG => (A, RNG), so this is just a
kind of function composition.
n def map[A,B](s: Rand[A])(f: A => B):Rand[B] =
rng => {
val (a, rng2) = s(rng)
(f(a), rng2) }
Department of Computer Science, the
University of Illinois at Chicago 22
Combinator flatMap

n flatMap allows us to generate a random A with


Rand[A], and then take that A and choose a
Rand[B] based on its value.
n def flatMap[A,B](f: Rand[A])
(g: A => Rand[B]): Rand[B] = {
rng => {
val (a,r1) = f(rng)
g(a)(r1)
}
}

Department of Computer Science, the


University of Illinois at Chicago 23
Time 2 Generalize!
n def map[S,A,B](a: S => (A,S))(f: A => B): S => (B,S)
n type State[S,+A] = S => (A,S)
n State is short for computation that carries some state
along, or state action, state transition, or even statement.
n case class State[S,+A](run: S => (A,S))
n Back to the RNG: type Rand[A] = State[RNG, A]
n def get[S]: State[S, S] = State(s => (s, s))
n def set[S](s: S): State[S, Unit] = State(_ => ((), s))
Together with the State combinators —unit, map,
map2, and flatMap—are all the tools we need to
implement any kind of state machine or stateful
program in a purely functional way.
Department of Computer Science, the
University of Illinois at Chicago 24
Reading

n Mandatory
q Functional Programming in Scala by
Paul Chiusano and Rúnar Bjarnason
Published by Manning Publications,
2014
n Chapters 1 and 6 + exercises
q Homework
q Exercises
q Q/A on Teams
Department of Computer Science, the
University of Illinois at Chicago

You might also like