SlideShare a Scribd company logo
1 of 47
Download to read offline
Playing with the State Monad
David Galichet	

Freelance Developer
Twitter : @dgalichet
Let’s start with a simple problem
3
2
1
0
0

1

2

3
A simple simulation
R1

R2

3

(A, A, R, A, A, A)
Score : 0

(A, R, A, L, A, A)

2

Score : 0

1
0
0

1

2

3
A simple simulation
R1

R2

3

(A, A, R, A, A, A)
Score : 1

(A, R, A, L, A, A)

2

Score : 0

1
0
0

1

2

3
A simple simulation
R1

R2

3

(A, A, R, A, A, A)
Score : 1

(A, R, A, L, A, A)

2

Score : 0

1
0
0

1

2

3
A simple simulation
R1

R2

3

(A, A, R, A, A, A)
Score : 1

(A, R, A, L, A, A)

2

Score : 0

1
0
0

1

2

3
A simple simulation
R1

R2

3

(A, A, R, A, A, A)
Score : 1

(A, R, A, L, A, A)

2

Score : 0

1
0
0

1

2

3
A simple simulation
R1

R2

3

(A, A, R, A, A, A)
Score : 1

(A, R, A, L, A, A)

2

Score : 0

1
0
0

1

2

3
A simple simulation
R1

R2

3

(A, A, R, A, A, A)
Score : 1

(A, R, A, L, A, A)

2

Score : 1

1
0
0

1

2

3
A simple simulation
R1

R2

3

(A, A, R, A, A, A)
Score : 2

(A, R, A, L, A, A)

2

Score : 1

1
0
0

1

2

3
A simple simulation
R1

R2

3

(A, A, R, A, A, A)
Score : 2

(A, R, A, L, A, A)

2

Score : 1

1
0
0

1

2

3
A simple simulation
R1

R2

3

(A, A, R, A, A, A)
Score : 2

(A, R, A, L, A, A)

2

Score : 1

1
0 R1 is blocked by R2 !
0

1

2

3
A simple simulation
R1

R2

3

(A, A, R, A, A, A)
Score : 2

(A, R, A, L, A, A)

2

Score : 1

1
0
0

1

2

3
A simple simulation
R1

R2

3

(A, A, R, A, A, A)
Score : 2

(A, R, A, L, A, A)

2

Score : 1

1
0
0

1

2

3
A simple simulation
R1

R2

3

(A, A, R, A, A, A)
Score : 2

(A, R, A, L, A, A)

2

Score : 1

1
0
0

1

2

3
The game rules
• We want to simulate two robots moving
through a nxm playground	

• Each robot can either turn on a direction
(North, South, East, West) or move one step
forward	

• Robots move or turn according to
instructions
The game rules
• A robot can’t go out of the playground	

• A robot will be blocked if another robot is on
the place	

• Some coins are spread on the playground	

• Robots gather coins when they move over it
Think about this game
• It appears that we will deal with many states
:	

• Playground with its coins	

• Robots with their positions and gathered
coins
We want functional purity
• Functional Purity has many advantages like
composability, idempotence, maintainability
and thread safety	

• We need to find a way to deal with states and
remain pure
Dealing with states
S => (S, A)
• S is the type of a state and A the type of a
computation	

• The outcome of this function is a new state
and a result
Chaining states computations
def chainStOps(!
c1: S => (S, A), !
c2: S => (S, A)!
): S => (S, A) = { s =>!
val (s1, _) = c1(s)!
c2(s1)!
}

Repeated many times, this can be error
prone !
Introducing State Monad
• The aim of the state monad is to abstract
over state manipulations
Introducing State Monad
trait State[S, +A] {!
def run(initial: S): (S, A)!
def map[B](f: A => B): State[S, B] = ???!
def flatMap[B](f: A => State[S, B]): State[S, B] = ???!
}!

!

object State {!
def apply[S, A](f: S => (S, A)): State[S, A] = ???!
}
Introducing State Monad
trait State[S, +A] {!
def run(initial: S): (S, A)!
def map[B](f: A => B): State[S, B] = ???!
def flatMap[B](f: A => State[S, B]): State[S, B] = ???!
}!

!

object State {!
def apply[S, A](f: S => (S, A)): State[S, A] = !
new State[S, A] {!
def run(initial: S): (S, A) = f(initial)!
}!
}
State Monad embed computation !
Introducing State Monad
trait State[S, +A] {!
def run(initial: S): (S, A)!

!

def map[B](f: A => B): State[S, B] = State { s =>!
val (s1, a) = run(s)!
(s1, f(a))!
}!
Don’t forget the definition:
!
State.apply(S => (S, A)): State[S,A]

!
!

def flatMap[B](f: A => State[S, B]): State[S, B] = ???!
}
Introducing State Monad
trait State[S, +A] {!
def run(initial: S): (S, A)!

!

def map[B](f: A => B): State[S, B] = State { s =>!
val (s1, a) = run(s)!
(s1, f(a))!
}!
Don’t forget the definition:
!
State.apply(S => (S, A)): State[S,A]

!
!

def flatMap[B](f: A => State[S, B]): State[S, B] =
State { s =>!
val (s1, a) = run(s)!
f(a).run(s1)!
}!
}
Coming back to our game !
• We drive robots using a list of instructions
sealed trait Instruction!
case object L extends Instruction // turn Left!
case object R extends Instruction // turn Right!
case object A extends Instruction // Go on
Coming back to our game !
• Each robot has a direction
sealed trait Direction {!
def turn(i: Instruction): Direction!
}!
case object North extends Direction {!
def turn(i: Instruction) = i match {!
case L => West!
case R => East!
case _ => this!
}!
}!
case object South extends Direction { ... }!
case object East extends Direction { ... }!
case object West extends Direction { ... }
Coming back to our game !
• A direction and a location define a position
case class Point(x: Int, y: Int)!

!

case class Position(point: Point, dir: Direction) {!
def move(s: Playground): Position = {!
val p1 = dir match {!
case North => copy(point = point.copy(y = point.y +
1))!
case South => ...!
}!
if (s.isPossiblePosition(p1)) p1 else this!
}!
def turn(instruction: Instruction): Position =
!
copy(direction = direction.turn(instruction))!
}
Coming back to our game !
• And each Robot is a player with a Score
sealed trait Player!
case object R1 extends Player!
case object R2 extends Player!

!

case class Score(player: Player, score: Int)
Coming back to our game !
• The state of each Robot is defined as :
case class Robot(!
player: Player, !
positions: List[Position], !
coins: List[Point] = Nil) {!
lazy val currentPosition = positions.head!

!
!

lazy val score = Score(player, coins.size)!

def addPosition(next: Position) = copy(positions =
next::positions)!

!

def addCoin(coin: Point) = copy(coins = coin::coins)!
}
Coming back to our game !
• Robots evolve in a playground :
case class Playground(!
bottomLeft: Point, topRight: Point, !
coins: Set[Point],!
r1: Robot, r2: Robot) {!

!
!
!
!

def isInPlayground(point: Point): Boolean =!
bottomLeft.x <= point.x && ...!
def isPossiblePosition(pos: Position): Boolean = ...!
lazy val scores = (r1.score, r2.score)!
def swapRobots(): Playground = copy(r1 = r2, r2 = r1)!

}
Look at what we did
• a set of Instructions,	

• a Position composed with Points and
Direction,	

• a definition for Players and Score,	

• a way to define Robot state	

• and a way to define Playground state
Let put these all together !
• Now, we need a method to process a single
instruction	

• And a method to process all instructions	

• The expected result is a State Monad that
will be run with the initial state of the
playground
Processing a single instruction
def processInstruction(i: Instruction)(s: Playground):
Playground = {!
val next = i match {!
case A => s.r1.currentPosition.move(s)!
case i => s.r1.currentPosition.turn(i)!
}!

!

if (s.coins.contains(next.point)) {!
s.copy(!
coins = s.coins - next.point, !
r1 = s.r1.addCoin(next.point).addPosition(next)!
)!
} else {!
s.copy(r1 = s.r1.addPosition(next))!
}!
}
Processing a single instruction
def processInstruction(i: Instruction)(s: Playground):
Playground = {!
val next = i match {!
case A => s.r1.currentPosition.move(s)!
case i => s.r1.currentPosition.turn(i)!
}!
We always process the robot on first position !

!

}

Robots will be swapped alternatively.
if (s.coins.contains(next.point)) {!
s.copy(!
coins = s.coins - next.point, !
r1 = s.r1.addCoin(next.point).addPosition(next)!
)!
} else {!
s.copy(r1 = s.r1.addPosition(next))!
}!
Quick reminder
trait State[S, +A] {!
def run(initial: S): (S, A)!
def map[B](f: A => B): State[S, B] = State { s =>!
val (s1, a) = run(s)!
(s1, f(a))!
}!
def flatMap[B](f: A => State[S, B]): State[S, B] =
State { s =>!
val (s1, a) = run(s)!
f(a).run(s1)!
}!
}!
object State {!
def apply[S, A](f: S => (S, A)): State[S, A] =!
new State[S, A] {!
def run(initial: S): (S, A) = f(initial)!
}!
}
Introducing new combinators
trait State[S, +A] {!
...!
}!
object State {!
def apply[S, A](f: S => (S, A)): State[S, A] =!
new State[S, A] {!
def run(initial: S): (S, A) = f(initial)!
}!

!

def get[S]: State[S, S] = State { s => (s, s) }!

!

def gets[S, A](f: S => A): State[S, A] = !
State { s => (s, f(s)) }!
}
Here comes the magic !
def compileInstructions(!
i1: List[Instruction], !
i2: List[Instruction]!
): State[Playground, (Score, Score)] = i1 match {!
case Nil if i2 == Nil => State.gets(_.scores)!
case Nil => State[Playground, (Score, Score)] { s =>
(s.swapRobots(), s.scores) !
}.flatMap { _ => compileInstructions(i2, i1) }!
case head::tail => State[Playground, (Score, Score)] !
{ s =>!
val s1 = processInstruction(head)(s)!
(s1.swapRobots(), s1.scores)!
}.flatMap { _ => compileInstructions(i2, tail) }!
}
Here comes the magic !
def compileInstructions(!
i1: List[Instruction], !
i2: List[Instruction]!
): State[Playground, (Score, Score)] = i1 match {!
case Nil if i2 == Nil => State.gets(_.scores)!
case Nil => State[Playground, (Score, Score)] { s =>
(s.swapRobots(), s.scores) !
}.flatMap { _ => compileInstructions(i2, i1) }!
case head::tail => State[Playground, (Score, Score)] !
{ s =>!
If both i1 and i2 are empty, we return a State
val s1 = processInstruction(head)(s)!
Monad with the run method implementation :
(s1.swapRobots(), s1.scores)!
s => (s, s.scores)!
}.flatMap { _ => compileInstructions(i2, tail) }!
This will return the Playground passed in argument
}
and the score as result.
Here comes the magic !
def compileInstructions(!
i1: List[Instruction], !
i2: List[Instruction]!
): State[Playground, (Score, Score)] = i1 match {!
case Nil if i2 == Nil => State.gets(_.scores)!
case Nil => State[Playground, (Score, Score)] { s =>
(s.swapRobots(), s.scores) !
}.flatMap { _ => compileInstructions(i2, Nil) }!
case head::tail => State[Playground, (Score, Score)] !
{ s =>!
val s1 = processInstruction(head)(s)!
(s1.swapRobots(), s1.scores)!
If i1 is empty, we return a State Monad with a
}.flatMap { _ that compileInstructions(i2, tail) }!
run method => swap robots in Playground
}
and returns scores.
Then we chain it with the processing of
instructions for the second list.
Here comes the magic !
We process
def compileInstructions(! i1 and return a new Playground where
robots are !
i1: List[Instruction],swapped.
Then we chain it with the processing of the instructions
i2: List[Instruction]!
i2 and tail of i1.
): State[Playground, of instructions are processed alternatively {!
Lists (Score, Score)] = i1 match !
case Nil if i2 == Nil => State.gets(_.scores)!
case Nil => State[Playground, (Score, Score)] { s =>
(s.swapRobots(), s.scores) !
}.flatMap { _ => compileInstructions(i2, i1) }!
case head::tail => State[Playground, (Score, Score)] !
{ s =>!
val s1 = processInstruction(head)(s)!
(s1.swapRobots(), s1.scores)!
}.flatMap { _ => compileInstructions(i2, tail) }!
}
Here comes the magic !
def compileInstructions(!
i1: List[Instruction], !
i2: List[Instruction]!
): State[Playground, (Score, Score)] = i1 match {!
case Nil if i2 == Nil => State.gets(_.scores)!
case Nil => State[Playground, (Score, Score)] { s =>
(s.swapRobots(), s.scores) !
}.flatMap { _ => compileInstructions(i2, i1) }!
case head::tail => State[Playground, (Score, Score)] !
{ s =>!
val s1 = processInstruction(head)(s)!
(s1.swapRobots(), s1.scores)!
}.flatMap { _ => compileInstructions(i2, tail) }!
}
Using for comprehensions
def getPositions(p: Playground): (Position, Position) =
(p.r1.currentPosition, p.r2.currentPosition)!

!

def enhanceResult(!
i1: List[Instruction], !
i2: List[Instruction]): State[Playground, (String,
(Position, Position))] = {!
for {!
scores <- compileInstructions(i1, i2)!
positions <- State.gets(getPositions)!
} yield (declareWinners(scores), positions)!
}
Conclusion
• State Monad simplify computations on states	

• Use it whenever you want to manipulate
states in a purely functional (parsing,
caching, validation ...)
To learn more about State Monad
• Functional programming in scala by Paul
Chiusano and Rúnar Bjarnason - This book is
awesome !	

• State Monad keynote by Michael Pilquist https://speakerdeck.com/mpilquist/scalazstate-monad	

• Learning scalaz by Eugene Yokota - http://
eed3si9n.com/learning-scalaz/State.html
Questions ?

More Related Content

What's hot

Scalaz 8: A Whole New Game
Scalaz 8: A Whole New GameScalaz 8: A Whole New Game
Scalaz 8: A Whole New GameJohn De Goes
 
Refactoring Functional Type Classes
Refactoring Functional Type ClassesRefactoring Functional Type Classes
Refactoring Functional Type ClassesJohn De Goes
 
λ | Lenses
λ | Lensesλ | Lenses
λ | LensesOpen-IT
 
Scala: Functioneel programmeren in een object georiënteerde wereld
Scala: Functioneel programmeren in een object georiënteerde wereldScala: Functioneel programmeren in een object georiënteerde wereld
Scala: Functioneel programmeren in een object georiënteerde wereldWerner Hofstra
 
First-Class Patterns
First-Class PatternsFirst-Class Patterns
First-Class PatternsJohn De Goes
 
OSCON Presentation: Developing High Performance Websites and Modern Apps with...
OSCON Presentation: Developing High Performance Websites and Modern Apps with...OSCON Presentation: Developing High Performance Websites and Modern Apps with...
OSCON Presentation: Developing High Performance Websites and Modern Apps with...Doris Chen
 
Oh, All the things you'll traverse
Oh, All the things you'll traverseOh, All the things you'll traverse
Oh, All the things you'll traverseLuka Jacobowitz
 
One Monad to Rule Them All
One Monad to Rule Them AllOne Monad to Rule Them All
One Monad to Rule Them AllJohn De Goes
 
Monad Transformers In The Wild
Monad Transformers In The WildMonad Transformers In The Wild
Monad Transformers In The WildStackMob Inc
 
Optics with monocle - Modeling the part and the whole
Optics with monocle - Modeling the part and the wholeOptics with monocle - Modeling the part and the whole
Optics with monocle - Modeling the part and the wholeIlan Godik
 
Quark: A Purely-Functional Scala DSL for Data Processing & Analytics
Quark: A Purely-Functional Scala DSL for Data Processing & AnalyticsQuark: A Purely-Functional Scala DSL for Data Processing & Analytics
Quark: A Purely-Functional Scala DSL for Data Processing & AnalyticsJohn De Goes
 
Post-Free: Life After Free Monads
Post-Free: Life After Free MonadsPost-Free: Life After Free Monads
Post-Free: Life After Free MonadsJohn De Goes
 
Type classes 101 - classification beyond inheritance
Type classes 101 - classification beyond inheritanceType classes 101 - classification beyond inheritance
Type classes 101 - classification beyond inheritanceAlexey Raga
 
Side by Side - Scala and Java Adaptations of Martin Fowler’s Javascript Refac...
Side by Side - Scala and Java Adaptations of Martin Fowler’s Javascript Refac...Side by Side - Scala and Java Adaptations of Martin Fowler’s Javascript Refac...
Side by Side - Scala and Java Adaptations of Martin Fowler’s Javascript Refac...Philip Schwarz
 
Introduction to Functional Programming with Scala
Introduction to Functional Programming with ScalaIntroduction to Functional Programming with Scala
Introduction to Functional Programming with ScalaDaniel Cukier
 
Blazing Fast, Pure Effects without Monads — LambdaConf 2018
Blazing Fast, Pure Effects without Monads — LambdaConf 2018Blazing Fast, Pure Effects without Monads — LambdaConf 2018
Blazing Fast, Pure Effects without Monads — LambdaConf 2018John De Goes
 
Atomically { Delete Your Actors }
Atomically { Delete Your Actors }Atomically { Delete Your Actors }
Atomically { Delete Your Actors }John De Goes
 
The Easy-Peasy-Lemon-Squeezy, Statically-Typed, Purely Functional Programming...
The Easy-Peasy-Lemon-Squeezy, Statically-Typed, Purely Functional Programming...The Easy-Peasy-Lemon-Squeezy, Statically-Typed, Purely Functional Programming...
The Easy-Peasy-Lemon-Squeezy, Statically-Typed, Purely Functional Programming...John De Goes
 

What's hot (20)

Scalaz 8: A Whole New Game
Scalaz 8: A Whole New GameScalaz 8: A Whole New Game
Scalaz 8: A Whole New Game
 
Refactoring Functional Type Classes
Refactoring Functional Type ClassesRefactoring Functional Type Classes
Refactoring Functional Type Classes
 
λ | Lenses
λ | Lensesλ | Lenses
λ | Lenses
 
Scala: Functioneel programmeren in een object georiënteerde wereld
Scala: Functioneel programmeren in een object georiënteerde wereldScala: Functioneel programmeren in een object georiënteerde wereld
Scala: Functioneel programmeren in een object georiënteerde wereld
 
Beyond Scala Lens
Beyond Scala LensBeyond Scala Lens
Beyond Scala Lens
 
First-Class Patterns
First-Class PatternsFirst-Class Patterns
First-Class Patterns
 
OSCON Presentation: Developing High Performance Websites and Modern Apps with...
OSCON Presentation: Developing High Performance Websites and Modern Apps with...OSCON Presentation: Developing High Performance Websites and Modern Apps with...
OSCON Presentation: Developing High Performance Websites and Modern Apps with...
 
Oh, All the things you'll traverse
Oh, All the things you'll traverseOh, All the things you'll traverse
Oh, All the things you'll traverse
 
One Monad to Rule Them All
One Monad to Rule Them AllOne Monad to Rule Them All
One Monad to Rule Them All
 
Monad Transformers In The Wild
Monad Transformers In The WildMonad Transformers In The Wild
Monad Transformers In The Wild
 
Optics with monocle - Modeling the part and the whole
Optics with monocle - Modeling the part and the wholeOptics with monocle - Modeling the part and the whole
Optics with monocle - Modeling the part and the whole
 
Quark: A Purely-Functional Scala DSL for Data Processing & Analytics
Quark: A Purely-Functional Scala DSL for Data Processing & AnalyticsQuark: A Purely-Functional Scala DSL for Data Processing & Analytics
Quark: A Purely-Functional Scala DSL for Data Processing & Analytics
 
Post-Free: Life After Free Monads
Post-Free: Life After Free MonadsPost-Free: Life After Free Monads
Post-Free: Life After Free Monads
 
Type classes 101 - classification beyond inheritance
Type classes 101 - classification beyond inheritanceType classes 101 - classification beyond inheritance
Type classes 101 - classification beyond inheritance
 
Side by Side - Scala and Java Adaptations of Martin Fowler’s Javascript Refac...
Side by Side - Scala and Java Adaptations of Martin Fowler’s Javascript Refac...Side by Side - Scala and Java Adaptations of Martin Fowler’s Javascript Refac...
Side by Side - Scala and Java Adaptations of Martin Fowler’s Javascript Refac...
 
Introduction to Functional Programming with Scala
Introduction to Functional Programming with ScalaIntroduction to Functional Programming with Scala
Introduction to Functional Programming with Scala
 
Blazing Fast, Pure Effects without Monads — LambdaConf 2018
Blazing Fast, Pure Effects without Monads — LambdaConf 2018Blazing Fast, Pure Effects without Monads — LambdaConf 2018
Blazing Fast, Pure Effects without Monads — LambdaConf 2018
 
Atomically { Delete Your Actors }
Atomically { Delete Your Actors }Atomically { Delete Your Actors }
Atomically { Delete Your Actors }
 
Scala intro workshop
Scala intro workshopScala intro workshop
Scala intro workshop
 
The Easy-Peasy-Lemon-Squeezy, Statically-Typed, Purely Functional Programming...
The Easy-Peasy-Lemon-Squeezy, Statically-Typed, Purely Functional Programming...The Easy-Peasy-Lemon-Squeezy, Statically-Typed, Purely Functional Programming...
The Easy-Peasy-Lemon-Squeezy, Statically-Typed, Purely Functional Programming...
 

Viewers also liked

Type class polymorphism
Type class polymorphismType class polymorphism
Type class polymorphismMayank Bairagi
 
Building a Functional Stream in Scala
Building a Functional Stream in ScalaBuilding a Functional Stream in Scala
Building a Functional Stream in ScalaDerek Wyatt
 
하스켈 프로그래밍 입문 3
하스켈 프로그래밍 입문 3하스켈 프로그래밍 입문 3
하스켈 프로그래밍 입문 3Kwang Yul Seo
 
mjprof: Monadic approach for JVM profiling
mjprof: Monadic approach for JVM profilingmjprof: Monadic approach for JVM profiling
mjprof: Monadic approach for JVM profilingHaim Yadid
 
(2015 06-16) Three Approaches to Monads
(2015 06-16) Three Approaches to Monads(2015 06-16) Three Approaches to Monads
(2015 06-16) Three Approaches to MonadsLawrence Evans
 
Functional Programming by Examples using Haskell
Functional Programming by Examples using HaskellFunctional Programming by Examples using Haskell
Functional Programming by Examples using Haskellgoncharenko
 
전자책산업동향과 서비스 모델 (Slide Share)
전자책산업동향과 서비스 모델 (Slide Share)전자책산업동향과 서비스 모델 (Slide Share)
전자책산업동향과 서비스 모델 (Slide Share)Joong Ho Lee
 
The Eff monad, one monad to rule them all
The Eff monad, one monad to rule them allThe Eff monad, one monad to rule them all
The Eff monad, one monad to rule them allEric Torreborre
 
Dr Frankenfunctor and the Monadster
Dr Frankenfunctor and the MonadsterDr Frankenfunctor and the Monadster
Dr Frankenfunctor and the MonadsterScott Wlaschin
 
Real-World Functional Programming @ Incubaid
Real-World Functional Programming @ IncubaidReal-World Functional Programming @ Incubaid
Real-World Functional Programming @ IncubaidNicolas Trangez
 
Haskell study 15
Haskell study 15Haskell study 15
Haskell study 15Nam Hyeonuk
 
Real world akka recepies v3
Real world akka recepies v3Real world akka recepies v3
Real world akka recepies v3shinolajla
 
Functional Programming in C# and F#
Functional Programming in C# and F#Functional Programming in C# and F#
Functional Programming in C# and F#Alfonso Garcia-Caro
 
Running Free with the Monads
Running Free with the MonadsRunning Free with the Monads
Running Free with the Monadskenbot
 
Enterprise Tic-Tac-Toe
Enterprise Tic-Tac-ToeEnterprise Tic-Tac-Toe
Enterprise Tic-Tac-ToeScott Wlaschin
 
Railway Oriented Programming
Railway Oriented ProgrammingRailway Oriented Programming
Railway Oriented ProgrammingScott Wlaschin
 
Les évolutions adaptatives
Les évolutions adaptativesLes évolutions adaptatives
Les évolutions adaptativesRESPONSIV
 
The Coming Intelligent Digital Assistant Era and Its Impact on Online Platforms
The Coming Intelligent Digital Assistant Era and Its Impact on Online PlatformsThe Coming Intelligent Digital Assistant Era and Its Impact on Online Platforms
The Coming Intelligent Digital Assistant Era and Its Impact on Online PlatformsCognizant
 

Viewers also liked (20)

Type class polymorphism
Type class polymorphismType class polymorphism
Type class polymorphism
 
Building a Functional Stream in Scala
Building a Functional Stream in ScalaBuilding a Functional Stream in Scala
Building a Functional Stream in Scala
 
하스켈 프로그래밍 입문 3
하스켈 프로그래밍 입문 3하스켈 프로그래밍 입문 3
하스켈 프로그래밍 입문 3
 
mjprof: Monadic approach for JVM profiling
mjprof: Monadic approach for JVM profilingmjprof: Monadic approach for JVM profiling
mjprof: Monadic approach for JVM profiling
 
(2015 06-16) Three Approaches to Monads
(2015 06-16) Three Approaches to Monads(2015 06-16) Three Approaches to Monads
(2015 06-16) Three Approaches to Monads
 
Functional Programming by Examples using Haskell
Functional Programming by Examples using HaskellFunctional Programming by Examples using Haskell
Functional Programming by Examples using Haskell
 
전자책산업동향과 서비스 모델 (Slide Share)
전자책산업동향과 서비스 모델 (Slide Share)전자책산업동향과 서비스 모델 (Slide Share)
전자책산업동향과 서비스 모델 (Slide Share)
 
Pratical eff
Pratical effPratical eff
Pratical eff
 
The Eff monad, one monad to rule them all
The Eff monad, one monad to rule them allThe Eff monad, one monad to rule them all
The Eff monad, one monad to rule them all
 
Dr Frankenfunctor and the Monadster
Dr Frankenfunctor and the MonadsterDr Frankenfunctor and the Monadster
Dr Frankenfunctor and the Monadster
 
Real-World Functional Programming @ Incubaid
Real-World Functional Programming @ IncubaidReal-World Functional Programming @ Incubaid
Real-World Functional Programming @ Incubaid
 
Haskell study 15
Haskell study 15Haskell study 15
Haskell study 15
 
Real world akka recepies v3
Real world akka recepies v3Real world akka recepies v3
Real world akka recepies v3
 
Functional Programming in C# and F#
Functional Programming in C# and F#Functional Programming in C# and F#
Functional Programming in C# and F#
 
Running Free with the Monads
Running Free with the MonadsRunning Free with the Monads
Running Free with the Monads
 
Enterprise Tic-Tac-Toe
Enterprise Tic-Tac-ToeEnterprise Tic-Tac-Toe
Enterprise Tic-Tac-Toe
 
The monad fear
The monad fearThe monad fear
The monad fear
 
Railway Oriented Programming
Railway Oriented ProgrammingRailway Oriented Programming
Railway Oriented Programming
 
Les évolutions adaptatives
Les évolutions adaptativesLes évolutions adaptatives
Les évolutions adaptatives
 
The Coming Intelligent Digital Assistant Era and Its Impact on Online Platforms
The Coming Intelligent Digital Assistant Era and Its Impact on Online PlatformsThe Coming Intelligent Digital Assistant Era and Its Impact on Online Platforms
The Coming Intelligent Digital Assistant Era and Its Impact on Online Platforms
 

Similar to Playing with State Monad

F# at GameSys
F# at GameSysF# at GameSys
F# at GameSysYan Cui
 
F# in the Real World (DDD EA)
F# in the Real World (DDD EA)F# in the Real World (DDD EA)
F# in the Real World (DDD EA)Yan Cui
 
Adventures In Data Compilation
Adventures In Data CompilationAdventures In Data Compilation
Adventures In Data CompilationNaughty Dog
 
Send + More = Money – Let’s mash 2 monads to solve a simple CSP
Send + More = Money – Let’s mash 2 monads to solve a simple CSPSend + More = Money – Let’s mash 2 monads to solve a simple CSP
Send + More = Money – Let’s mash 2 monads to solve a simple CSPFilippo Vitale
 
The Ring programming language version 1.10 book - Part 71 of 212
The Ring programming language version 1.10 book - Part 71 of 212The Ring programming language version 1.10 book - Part 71 of 212
The Ring programming language version 1.10 book - Part 71 of 212Mahmoud Samir Fayed
 
Scaladays 2011 - The Ease of Scalaz
Scaladays 2011 - The Ease of ScalazScaladays 2011 - The Ease of Scalaz
Scaladays 2011 - The Ease of ScalazHeiko Seeberger
 
ACI-Webinar-3-MinMaxAlphaBetaPruning-TicTacToe.pptx
ACI-Webinar-3-MinMaxAlphaBetaPruning-TicTacToe.pptxACI-Webinar-3-MinMaxAlphaBetaPruning-TicTacToe.pptx
ACI-Webinar-3-MinMaxAlphaBetaPruning-TicTacToe.pptxssuser1eba67
 
PUSH DOWN AUTOMATA VS TURING MACHINE
PUSH DOWN AUTOMATA VS TURING MACHINEPUSH DOWN AUTOMATA VS TURING MACHINE
PUSH DOWN AUTOMATA VS TURING MACHINEAbhishek Shivhare
 
12IRGeneration.pdf
12IRGeneration.pdf12IRGeneration.pdf
12IRGeneration.pdfSHUJEHASSAN
 
Scala kansai summit-2016
Scala kansai summit-2016Scala kansai summit-2016
Scala kansai summit-2016Naoki Kitora
 
Brief tour of psp-std
Brief tour of psp-stdBrief tour of psp-std
Brief tour of psp-stdPaul Phillips
 
Stateモナドの解説 後編
Stateモナドの解説 後編Stateモナドの解説 後編
Stateモナドの解説 後編Masahiro Honma
 
ScotRuby - Dark side of ruby
ScotRuby - Dark side of rubyScotRuby - Dark side of ruby
ScotRuby - Dark side of rubyGautam Rege
 
lalr. fo engineering student those who to
lalr. fo engineering student those who tolalr. fo engineering student those who to
lalr. fo engineering student those who toHjJordTzong
 
Developing High Performance Websites and Modern Apps with JavaScript and HTML5
Developing High Performance Websites and Modern Apps with JavaScript and HTML5Developing High Performance Websites and Modern Apps with JavaScript and HTML5
Developing High Performance Websites and Modern Apps with JavaScript and HTML5Doris Chen
 
AI - Introduction to Markov Principles
AI - Introduction to Markov PrinciplesAI - Introduction to Markov Principles
AI - Introduction to Markov PrinciplesAndrew Ferlitsch
 
Help with root locus homework1
Help with root locus homework1Help with root locus homework1
Help with root locus homework1Assignmentpedia
 

Similar to Playing with State Monad (20)

F# at GameSys
F# at GameSysF# at GameSys
F# at GameSys
 
F# in the Real World (DDD EA)
F# in the Real World (DDD EA)F# in the Real World (DDD EA)
F# in the Real World (DDD EA)
 
Ch4b
Ch4bCh4b
Ch4b
 
Provenance Games
Provenance GamesProvenance Games
Provenance Games
 
Adventures In Data Compilation
Adventures In Data CompilationAdventures In Data Compilation
Adventures In Data Compilation
 
Send + More = Money – Let’s mash 2 monads to solve a simple CSP
Send + More = Money – Let’s mash 2 monads to solve a simple CSPSend + More = Money – Let’s mash 2 monads to solve a simple CSP
Send + More = Money – Let’s mash 2 monads to solve a simple CSP
 
The Ring programming language version 1.10 book - Part 71 of 212
The Ring programming language version 1.10 book - Part 71 of 212The Ring programming language version 1.10 book - Part 71 of 212
The Ring programming language version 1.10 book - Part 71 of 212
 
Scaladays 2011 - The Ease of Scalaz
Scaladays 2011 - The Ease of ScalazScaladays 2011 - The Ease of Scalaz
Scaladays 2011 - The Ease of Scalaz
 
ACI-Webinar-3-MinMaxAlphaBetaPruning-TicTacToe.pptx
ACI-Webinar-3-MinMaxAlphaBetaPruning-TicTacToe.pptxACI-Webinar-3-MinMaxAlphaBetaPruning-TicTacToe.pptx
ACI-Webinar-3-MinMaxAlphaBetaPruning-TicTacToe.pptx
 
PUSH DOWN AUTOMATA VS TURING MACHINE
PUSH DOWN AUTOMATA VS TURING MACHINEPUSH DOWN AUTOMATA VS TURING MACHINE
PUSH DOWN AUTOMATA VS TURING MACHINE
 
12IRGeneration.pdf
12IRGeneration.pdf12IRGeneration.pdf
12IRGeneration.pdf
 
Scala kansai summit-2016
Scala kansai summit-2016Scala kansai summit-2016
Scala kansai summit-2016
 
Brief tour of psp-std
Brief tour of psp-stdBrief tour of psp-std
Brief tour of psp-std
 
Stateモナドの解説 後編
Stateモナドの解説 後編Stateモナドの解説 後編
Stateモナドの解説 後編
 
ScotRuby - Dark side of ruby
ScotRuby - Dark side of rubyScotRuby - Dark side of ruby
ScotRuby - Dark side of ruby
 
Deep RL.pdf
Deep RL.pdfDeep RL.pdf
Deep RL.pdf
 
lalr. fo engineering student those who to
lalr. fo engineering student those who tolalr. fo engineering student those who to
lalr. fo engineering student those who to
 
Developing High Performance Websites and Modern Apps with JavaScript and HTML5
Developing High Performance Websites and Modern Apps with JavaScript and HTML5Developing High Performance Websites and Modern Apps with JavaScript and HTML5
Developing High Performance Websites and Modern Apps with JavaScript and HTML5
 
AI - Introduction to Markov Principles
AI - Introduction to Markov PrinciplesAI - Introduction to Markov Principles
AI - Introduction to Markov Principles
 
Help with root locus homework1
Help with root locus homework1Help with root locus homework1
Help with root locus homework1
 

Recently uploaded

"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...Fwdays
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Enterprise Knowledge
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):comworks
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024Lorenzo Miniero
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsMemoori
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024The Digital Insurer
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clashcharlottematthew16
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxhariprasad279825
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyAlfredo García Lavilla
 
costume and set research powerpoint presentation
costume and set research powerpoint presentationcostume and set research powerpoint presentation
costume and set research powerpoint presentationphoebematthew05
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticscarlostorres15106
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr LapshynFwdays
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxNavinnSomaal
 

Recently uploaded (20)

"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial Buildings
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clash
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptx
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easy
 
costume and set research powerpoint presentation
costume and set research powerpoint presentationcostume and set research powerpoint presentation
costume and set research powerpoint presentation
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptx
 

Playing with State Monad

  • 1. Playing with the State Monad David Galichet Freelance Developer Twitter : @dgalichet
  • 2. Let’s start with a simple problem 3 2 1 0 0 1 2 3
  • 3. A simple simulation R1 R2 3 (A, A, R, A, A, A) Score : 0 (A, R, A, L, A, A) 2 Score : 0 1 0 0 1 2 3
  • 4. A simple simulation R1 R2 3 (A, A, R, A, A, A) Score : 1 (A, R, A, L, A, A) 2 Score : 0 1 0 0 1 2 3
  • 5. A simple simulation R1 R2 3 (A, A, R, A, A, A) Score : 1 (A, R, A, L, A, A) 2 Score : 0 1 0 0 1 2 3
  • 6. A simple simulation R1 R2 3 (A, A, R, A, A, A) Score : 1 (A, R, A, L, A, A) 2 Score : 0 1 0 0 1 2 3
  • 7. A simple simulation R1 R2 3 (A, A, R, A, A, A) Score : 1 (A, R, A, L, A, A) 2 Score : 0 1 0 0 1 2 3
  • 8. A simple simulation R1 R2 3 (A, A, R, A, A, A) Score : 1 (A, R, A, L, A, A) 2 Score : 0 1 0 0 1 2 3
  • 9. A simple simulation R1 R2 3 (A, A, R, A, A, A) Score : 1 (A, R, A, L, A, A) 2 Score : 1 1 0 0 1 2 3
  • 10. A simple simulation R1 R2 3 (A, A, R, A, A, A) Score : 2 (A, R, A, L, A, A) 2 Score : 1 1 0 0 1 2 3
  • 11. A simple simulation R1 R2 3 (A, A, R, A, A, A) Score : 2 (A, R, A, L, A, A) 2 Score : 1 1 0 0 1 2 3
  • 12. A simple simulation R1 R2 3 (A, A, R, A, A, A) Score : 2 (A, R, A, L, A, A) 2 Score : 1 1 0 R1 is blocked by R2 ! 0 1 2 3
  • 13. A simple simulation R1 R2 3 (A, A, R, A, A, A) Score : 2 (A, R, A, L, A, A) 2 Score : 1 1 0 0 1 2 3
  • 14. A simple simulation R1 R2 3 (A, A, R, A, A, A) Score : 2 (A, R, A, L, A, A) 2 Score : 1 1 0 0 1 2 3
  • 15. A simple simulation R1 R2 3 (A, A, R, A, A, A) Score : 2 (A, R, A, L, A, A) 2 Score : 1 1 0 0 1 2 3
  • 16. The game rules • We want to simulate two robots moving through a nxm playground • Each robot can either turn on a direction (North, South, East, West) or move one step forward • Robots move or turn according to instructions
  • 17. The game rules • A robot can’t go out of the playground • A robot will be blocked if another robot is on the place • Some coins are spread on the playground • Robots gather coins when they move over it
  • 18. Think about this game • It appears that we will deal with many states : • Playground with its coins • Robots with their positions and gathered coins
  • 19. We want functional purity • Functional Purity has many advantages like composability, idempotence, maintainability and thread safety • We need to find a way to deal with states and remain pure
  • 20. Dealing with states S => (S, A) • S is the type of a state and A the type of a computation • The outcome of this function is a new state and a result
  • 21. Chaining states computations def chainStOps(! c1: S => (S, A), ! c2: S => (S, A)! ): S => (S, A) = { s =>! val (s1, _) = c1(s)! c2(s1)! } Repeated many times, this can be error prone !
  • 22. Introducing State Monad • The aim of the state monad is to abstract over state manipulations
  • 23. Introducing State Monad trait State[S, +A] {! def run(initial: S): (S, A)! def map[B](f: A => B): State[S, B] = ???! def flatMap[B](f: A => State[S, B]): State[S, B] = ???! }! ! object State {! def apply[S, A](f: S => (S, A)): State[S, A] = ???! }
  • 24. Introducing State Monad trait State[S, +A] {! def run(initial: S): (S, A)! def map[B](f: A => B): State[S, B] = ???! def flatMap[B](f: A => State[S, B]): State[S, B] = ???! }! ! object State {! def apply[S, A](f: S => (S, A)): State[S, A] = ! new State[S, A] {! def run(initial: S): (S, A) = f(initial)! }! } State Monad embed computation !
  • 25. Introducing State Monad trait State[S, +A] {! def run(initial: S): (S, A)! ! def map[B](f: A => B): State[S, B] = State { s =>! val (s1, a) = run(s)! (s1, f(a))! }! Don’t forget the definition: ! State.apply(S => (S, A)): State[S,A] ! ! def flatMap[B](f: A => State[S, B]): State[S, B] = ???! }
  • 26. Introducing State Monad trait State[S, +A] {! def run(initial: S): (S, A)! ! def map[B](f: A => B): State[S, B] = State { s =>! val (s1, a) = run(s)! (s1, f(a))! }! Don’t forget the definition: ! State.apply(S => (S, A)): State[S,A] ! ! def flatMap[B](f: A => State[S, B]): State[S, B] = State { s =>! val (s1, a) = run(s)! f(a).run(s1)! }! }
  • 27. Coming back to our game ! • We drive robots using a list of instructions sealed trait Instruction! case object L extends Instruction // turn Left! case object R extends Instruction // turn Right! case object A extends Instruction // Go on
  • 28. Coming back to our game ! • Each robot has a direction sealed trait Direction {! def turn(i: Instruction): Direction! }! case object North extends Direction {! def turn(i: Instruction) = i match {! case L => West! case R => East! case _ => this! }! }! case object South extends Direction { ... }! case object East extends Direction { ... }! case object West extends Direction { ... }
  • 29. Coming back to our game ! • A direction and a location define a position case class Point(x: Int, y: Int)! ! case class Position(point: Point, dir: Direction) {! def move(s: Playground): Position = {! val p1 = dir match {! case North => copy(point = point.copy(y = point.y + 1))! case South => ...! }! if (s.isPossiblePosition(p1)) p1 else this! }! def turn(instruction: Instruction): Position = ! copy(direction = direction.turn(instruction))! }
  • 30. Coming back to our game ! • And each Robot is a player with a Score sealed trait Player! case object R1 extends Player! case object R2 extends Player! ! case class Score(player: Player, score: Int)
  • 31. Coming back to our game ! • The state of each Robot is defined as : case class Robot(! player: Player, ! positions: List[Position], ! coins: List[Point] = Nil) {! lazy val currentPosition = positions.head! ! ! lazy val score = Score(player, coins.size)! def addPosition(next: Position) = copy(positions = next::positions)! ! def addCoin(coin: Point) = copy(coins = coin::coins)! }
  • 32. Coming back to our game ! • Robots evolve in a playground : case class Playground(! bottomLeft: Point, topRight: Point, ! coins: Set[Point],! r1: Robot, r2: Robot) {! ! ! ! ! def isInPlayground(point: Point): Boolean =! bottomLeft.x <= point.x && ...! def isPossiblePosition(pos: Position): Boolean = ...! lazy val scores = (r1.score, r2.score)! def swapRobots(): Playground = copy(r1 = r2, r2 = r1)! }
  • 33. Look at what we did • a set of Instructions, • a Position composed with Points and Direction, • a definition for Players and Score, • a way to define Robot state • and a way to define Playground state
  • 34. Let put these all together ! • Now, we need a method to process a single instruction • And a method to process all instructions • The expected result is a State Monad that will be run with the initial state of the playground
  • 35. Processing a single instruction def processInstruction(i: Instruction)(s: Playground): Playground = {! val next = i match {! case A => s.r1.currentPosition.move(s)! case i => s.r1.currentPosition.turn(i)! }! ! if (s.coins.contains(next.point)) {! s.copy(! coins = s.coins - next.point, ! r1 = s.r1.addCoin(next.point).addPosition(next)! )! } else {! s.copy(r1 = s.r1.addPosition(next))! }! }
  • 36. Processing a single instruction def processInstruction(i: Instruction)(s: Playground): Playground = {! val next = i match {! case A => s.r1.currentPosition.move(s)! case i => s.r1.currentPosition.turn(i)! }! We always process the robot on first position ! ! } Robots will be swapped alternatively. if (s.coins.contains(next.point)) {! s.copy(! coins = s.coins - next.point, ! r1 = s.r1.addCoin(next.point).addPosition(next)! )! } else {! s.copy(r1 = s.r1.addPosition(next))! }!
  • 37. Quick reminder trait State[S, +A] {! def run(initial: S): (S, A)! def map[B](f: A => B): State[S, B] = State { s =>! val (s1, a) = run(s)! (s1, f(a))! }! def flatMap[B](f: A => State[S, B]): State[S, B] = State { s =>! val (s1, a) = run(s)! f(a).run(s1)! }! }! object State {! def apply[S, A](f: S => (S, A)): State[S, A] =! new State[S, A] {! def run(initial: S): (S, A) = f(initial)! }! }
  • 38. Introducing new combinators trait State[S, +A] {! ...! }! object State {! def apply[S, A](f: S => (S, A)): State[S, A] =! new State[S, A] {! def run(initial: S): (S, A) = f(initial)! }! ! def get[S]: State[S, S] = State { s => (s, s) }! ! def gets[S, A](f: S => A): State[S, A] = ! State { s => (s, f(s)) }! }
  • 39. Here comes the magic ! def compileInstructions(! i1: List[Instruction], ! i2: List[Instruction]! ): State[Playground, (Score, Score)] = i1 match {! case Nil if i2 == Nil => State.gets(_.scores)! case Nil => State[Playground, (Score, Score)] { s => (s.swapRobots(), s.scores) ! }.flatMap { _ => compileInstructions(i2, i1) }! case head::tail => State[Playground, (Score, Score)] ! { s =>! val s1 = processInstruction(head)(s)! (s1.swapRobots(), s1.scores)! }.flatMap { _ => compileInstructions(i2, tail) }! }
  • 40. Here comes the magic ! def compileInstructions(! i1: List[Instruction], ! i2: List[Instruction]! ): State[Playground, (Score, Score)] = i1 match {! case Nil if i2 == Nil => State.gets(_.scores)! case Nil => State[Playground, (Score, Score)] { s => (s.swapRobots(), s.scores) ! }.flatMap { _ => compileInstructions(i2, i1) }! case head::tail => State[Playground, (Score, Score)] ! { s =>! If both i1 and i2 are empty, we return a State val s1 = processInstruction(head)(s)! Monad with the run method implementation : (s1.swapRobots(), s1.scores)! s => (s, s.scores)! }.flatMap { _ => compileInstructions(i2, tail) }! This will return the Playground passed in argument } and the score as result.
  • 41. Here comes the magic ! def compileInstructions(! i1: List[Instruction], ! i2: List[Instruction]! ): State[Playground, (Score, Score)] = i1 match {! case Nil if i2 == Nil => State.gets(_.scores)! case Nil => State[Playground, (Score, Score)] { s => (s.swapRobots(), s.scores) ! }.flatMap { _ => compileInstructions(i2, Nil) }! case head::tail => State[Playground, (Score, Score)] ! { s =>! val s1 = processInstruction(head)(s)! (s1.swapRobots(), s1.scores)! If i1 is empty, we return a State Monad with a }.flatMap { _ that compileInstructions(i2, tail) }! run method => swap robots in Playground } and returns scores. Then we chain it with the processing of instructions for the second list.
  • 42. Here comes the magic ! We process def compileInstructions(! i1 and return a new Playground where robots are ! i1: List[Instruction],swapped. Then we chain it with the processing of the instructions i2: List[Instruction]! i2 and tail of i1. ): State[Playground, of instructions are processed alternatively {! Lists (Score, Score)] = i1 match ! case Nil if i2 == Nil => State.gets(_.scores)! case Nil => State[Playground, (Score, Score)] { s => (s.swapRobots(), s.scores) ! }.flatMap { _ => compileInstructions(i2, i1) }! case head::tail => State[Playground, (Score, Score)] ! { s =>! val s1 = processInstruction(head)(s)! (s1.swapRobots(), s1.scores)! }.flatMap { _ => compileInstructions(i2, tail) }! }
  • 43. Here comes the magic ! def compileInstructions(! i1: List[Instruction], ! i2: List[Instruction]! ): State[Playground, (Score, Score)] = i1 match {! case Nil if i2 == Nil => State.gets(_.scores)! case Nil => State[Playground, (Score, Score)] { s => (s.swapRobots(), s.scores) ! }.flatMap { _ => compileInstructions(i2, i1) }! case head::tail => State[Playground, (Score, Score)] ! { s =>! val s1 = processInstruction(head)(s)! (s1.swapRobots(), s1.scores)! }.flatMap { _ => compileInstructions(i2, tail) }! }
  • 44. Using for comprehensions def getPositions(p: Playground): (Position, Position) = (p.r1.currentPosition, p.r2.currentPosition)! ! def enhanceResult(! i1: List[Instruction], ! i2: List[Instruction]): State[Playground, (String, (Position, Position))] = {! for {! scores <- compileInstructions(i1, i2)! positions <- State.gets(getPositions)! } yield (declareWinners(scores), positions)! }
  • 45. Conclusion • State Monad simplify computations on states • Use it whenever you want to manipulate states in a purely functional (parsing, caching, validation ...)
  • 46. To learn more about State Monad • Functional programming in scala by Paul Chiusano and Rúnar Bjarnason - This book is awesome ! • State Monad keynote by Michael Pilquist https://speakerdeck.com/mpilquist/scalazstate-monad • Learning scalaz by Eugene Yokota - http:// eed3si9n.com/learning-scalaz/State.html