SlideShare a Scribd company logo
1 of 13
Download to read offline
Functional Core and Imperative Shell
Game of Life Example
See a program structure flowchart used to highlight how an FP program breaks down into a functional core and imperative shell
View a program structure flowchart for the Game of Life
See the code for Game of Life’s functional core and imperative shell, both in Haskell and in Scala
Polyglot FP for Fun and Profit – Haskell and Scala
Graham Hutton
@haskellhutt @VBragilevsky
Vitaly Bragilevsky
𝜆
functional	
core
imperative
shell
@philip_schwarz
slides by https://www.slideshare.net/pjschwarz
In Haskell in Depth, Vitaly Bragilevsky visualises certain aspects of his programs using program structure flowcharts.
One of the things shown by his diagrams is how the programs break down into a pure part and an I/O part, i.e. into a
functional core and an imperative shell.
In this short slide deck we do the following:
• create a program structure flowchart for the Game of Life
• show how Game of Life code consists of a functional core and an imperative shell
@philip_schwarz
@VBragilevsky
• User input is represented by parallelograms.
• All functions are represented by rectangles.
• Some of the functions are executing I/O actions. These are shown in the central part of the flowchart.
• Other functions are pure. They are given on the right-hand side.
• Diamonds traditionally represent choices made within a program.
• Function calls are represented by rectangles below and to the right of a caller.
• Several calls within a function are combined with a dashed line.
• Arrows in this flowchart represent moving data between the user and the program and between functions within the program.
READING A PROGRAM STRUCTURE FLOWCHART
I’ve tried to present all the components of the program in a program
structure flowchart: user input, actions in the I/O part of the program,
and their relations with the pure functions. I use the following notation
Vitaly Bragilevsky
If you would like an introduction to the notion of ’functional core, imperative shell’, see slides 15-20 of the second slide deck below.
If you want an explanation of the Game of Life code that we’ll be looking at next, see the first slide deck for Haskell, and the remaining two for Scala.
OOO OOO
O O O O
O O O O
O O O O
OOO OOO
OOO OOO
O O O O
O O O O
O O O O
OOO OOO
O O
O O
OO OO
OOO OO OO OOO
O O O O O O
OO OO
OO OO
O O O O O O
OOO OO OO OOO
OO OO
O O
O O
OO OO
OO OO
O O O O O O
OOO OO OO OOO
O O O O O O
OOO OOO
OOO OOO
O O O O O O
OOO OO OO OOO
O O O O O O
OO OO
OO OO
If we run the upcoming Game of Life program with a 20 by 20
board configured with the first generation of a Pulsar, the
program cycles forever through the following three patterns
pulsar :: Board
pulsar =
[(4, 2),(5, 2),(6, 2),(10, 2),(11, 2),(12, 2),
(2, 4),(7, 4),( 9, 4),(14, 4),
(2, 5),(7, 5),( 9, 5),(14, 5),
(2, 6),(7, 6),( 9, 6),(14, 6),
(4, 7),(5, 7),(6, 7),(10, 7),(11, 7),(12, 7),
(4, 9),(5, 9),(6, 9),(10, 9),(11, 9),(12, 9),
(2,10),(7,10),( 9,10),(14,10),
(2,11),(7,11),( 9,11),(14,11),
(2,12),(7,12),( 9,12),(14,12),
(4,14),(5,14),(6,14),(10,14),(11,14),(12,14)]
type Pos = (Int,Int) width :: Int
width = 20
type Board = [Pos] height :: Int
height = 20
The next slide shows a simple program structure flowchart for the Game of Life
program.
The rest of the slides show the following:
1. Haskell code for the program’s imperative shell
2. Haskell code for its functional core
3. .structure flowchart for the program (Scala version)
4. .Scala code for the imperative shell
5. .Scala code for the functional core
The Haskell Game of Life code is the one found in Graham Hutton’s book, Programming
in Haskell, with a handful of very minor changes, e.g.
• added an extra invocation of a function in order to move the cursor out of the way
after drawing a generation
• added data for the first pulsar generation
User Input I/O part Pure part
main
cls
showcells
nextgen
life
clears screen
prints cells to screen
wait
main :: IO ()
main = life(pulsar)
nextgen :: Board -> Board
showcells :: Board -> IO ()
cls :: IO ()
wait :: Int -> IO ()
life :: Board -> IO ()
life b = do
cls
showcells b
goto (width+1,height+1)
wait 500000
life (nextgen b)
FUNCTIONAL CORE
IMPERATIVE SHELL
goto moves cursor to bottom right
goto :: Pos -> IO ()
Graham Hutton
@haskellhutt
cls :: IO ()
cls = putStr "ESC[2J"
showcells :: Board -> IO ()
showcells b = sequence_ [writeat p "O" | p <- b]
wait :: Int -> IO ()
wait n = sequence_ [return () | _ <- [1..n]]
main :: IO ()
main = life(pulsar)
life :: Board -> IO ()
life b = do cls
showcells b
goto (width + 1, height + 1)
wait 500000
life (nextgen b)
writeat :: Pos -> String -> IO ()
writeat p xs = do goto p
putStr xs
goto :: Pos -> IO ()
goto (x,y) =
putStr ("ESC[" ++ show y ++ ";"
++ show x ++ "H")
putStr :: String -> IO ()
putStr [] = return ()
putStr (x:xs) = do putChar x
putStr xs
IMPERATIVE SHELL
Graham Hutton
@haskellhutt
nextgen :: Board -> Board
nextgen b = survivors b ++ births b
survivors :: Board -> [Pos]
survivors b =
[p | p <- b,
elem (liveneighbs b p) [2,3]]
births :: Board -> [Pos]
births b = [p | p <- rmdups (concat (map neighbs b)),
isEmpty b p,
liveneighbs b p == 3]
neighbs :: Pos -> [Pos]
neighbs (x,y) = map wrap [(x-1, y-1), (x, y-1),
(x+1, y-1), (x-1, y ),
(x+1, y), (x-1, y+1),
(x, y+1), (x+1, y+1)]
wrap :: Pos -> Pos
wrap (x,y) = (((x-1) `mod` width) + 1,
((y-1) `mod` height) + 1)
width :: Int height :: Int
width = 20 height = 20
rmdups :: Eq a => [a] -> [a]
rmdups [] = []
rmdups (x:xs) = x : rmdups (filter (/= x) xs)
isEmpty :: Board -> Pos -> Bool
isEmpty b p = not (isAlive b p)
liveneighbs :: Board -> Pos -> Int
liveneighbs b = length.filter(isAlive b).neighbs
isAlive :: Board -> Pos -> Bool
isAlive b p = elem p b
pulsar :: Board
pulsar =
[(4, 2),(5, 2),(6, 2),(10, 2),(11, 2),(12, 2),
(2, 4),(7, 4),( 9, 4),(14, 4),
(2, 5),(7, 5),( 9, 5),(14, 5),
(2, 6),(7, 6),( 9, 6),(14, 6),
(4, 7),(5, 7),(6, 7),(10, 7),(11, 7),(12, 7),
(4, 9),(5, 9),(6, 9),(10, 9),(11, 9),(12, 9),
(2,10),(7,10),( 9,10),(14,10),
(2,11),(7,11),( 9,11),(14,11),
(2,12),(7,12),( 9,12),(14,12),
(4,14),(5,14),(6,14),(10,14),(11,14),(12,14)]
type Pos = (Int,Int)
type Board = [Pos]
FUNCTIONAL CORE
User Input I/O part Pure part
main
cls
showcells
nextgen
life
clears screen
prints cells to screen
wait
def nextgen(b:Board):Board
FUNCTIONAL CORE
IMPERATIVE SHELL
goto moves cursor to bottom right
def showCells(b: Board): IO[Unit]
def cls: IO[Unit]
def wait(n:Int): IO[Unit]
def life(b: Board): IO[Unit] =
cls *>
showCells(b) *>
goto(width+1,height+1) *>
wait(1_000_000) >>
life(nextgen(b))
val main: IO[Unit] =
life(pulsar)
def goto(p: Pos): IO[Unit]
val main: IO[Unit] = life(pulsar)
def life(b: Board): IO[Unit] =
cls *>
showCells(b) *>
goto(width+1,height+1) *>
wait(1_000_000) >>
life(nextgen(b))
def cls: IO[Unit] = putStr("u001B[2J")
def showCells(b: Board): IO[Unit] =
( for { p <- b } yield writeAt(p, "O") ).sequence_
def wait(n:Int): IO[Unit] = List.fill(n)(IO.unit).sequence_
def writeAt(p: Pos, s: String): IO[Unit] =
goto(p) *> putStr(s)
def goto(p: Pos): IO[Unit] = p match {
case (x,y) => putStr(s"u001B[${y};${x}H")
}
def putStr(s: String): IO[Unit] =
IO { scala.Predef.print(s) }
IMPERATIVE SHELL import cats.implicits._, cats.effect.IO
main.unsafeRunSync
def nextgen(b: Board): Board = survivors(b) ++ births(b)
def survivors(b: Board): List[Pos] =
for {
p <- b
if List(2,3) contains liveneighbs(b)(p)
} yield p
def births(b: Board): List[Pos] =
for {
p <- rmdups(b flatMap neighbs)
if isEmpty(b)(p)
if liveneighbs(b)(p) == 3
} yield p
def rmdups[A](l: List[A]): List[A] = l match {
case Nil => Nil
case x::xs => x::rmdups(xs filter(_ != x)) }
def isEmpty(b: Board)(p: Pos): Boolean =
!(isAlive(b)(p))
def liveneighbs(b: Board)(p: Pos): Int =
neighbs(p).filter(isAlive(b)).length
def isAlive(b: Board)(p: Pos): Boolean =
b contains p
def neighbs(p: Pos): List[Pos] = p match {
case (x,y) => List(
(x - 1, y - 1), (x, y - 1), (x + 1, y - 1),
(x - 1, y ), /* cell */ (x + 1, y ),
(x - 1, y + 1), (x, y + 1), (x + 1, y + 1)
) map wrap }
def wrap(p: Pos): Pos = p match {
case (x, y) => (((x - 1) % width) + 1,
((y - 1) % height) + 1) }
val width = 20 val height = 20
val pulsar: Board = List(
(4, 2),(5, 2),(6, 2),(10, 2),(11, 2),(12, 2),
(2, 4),(7, 4),( 9, 4),(14, 4),
(2, 5),(7, 5),( 9, 5),(14, 5),
(2, 6),(7, 6),( 9, 6),(14, 6),
(4, 7),(5, 7),(6, 7),(10, 7),(11, 7),(12, 7),
(4, 9),(5, 9),(6, 9),(10, 9),(11, 9),(12, 9),
(2,10),(7,10),( 9,10),(14,10),
(2,11),(7,11),( 9,11),(14,11),
(2,12),(7,12),( 9,12),(14,12),
(4,14),(5,14),(6,14),(10,14),(11,14),(12,14)])
FUNCTIONAL CORE
type Pos = (Int, Int)
type Board = List[Pos]
If you want to run the programs, you can find them here:
• https://github.com/philipschwarz/functional-core-imperative-shell-scala
• https://github.com/philipschwarz/functional-core-imperative-shell-haskell
That’s all.
I hope you found it useful.
See you soon.
@philip_schwarz

More Related Content

What's hot

Sequence and Traverse - Part 1
Sequence and Traverse - Part 1Sequence and Traverse - Part 1
Sequence and Traverse - Part 1Philip Schwarz
 
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part ...
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part ...Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part ...
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part ...Philip Schwarz
 
The aggregate function - from sequential and parallel folds to parallel aggre...
The aggregate function - from sequential and parallel folds to parallel aggre...The aggregate function - from sequential and parallel folds to parallel aggre...
The aggregate function - from sequential and parallel folds to parallel aggre...Philip Schwarz
 
‘go-to’ general-purpose sequential collections - from Java To Scala
‘go-to’ general-purpose sequential collections -from Java To Scala‘go-to’ general-purpose sequential collections -from Java To Scala
‘go-to’ general-purpose sequential collections - from Java To ScalaPhilip Schwarz
 
Sequence and Traverse - Part 2
Sequence and Traverse - Part 2Sequence and Traverse - Part 2
Sequence and Traverse - Part 2Philip Schwarz
 
Http4s, Doobie and Circe: The Functional Web Stack
Http4s, Doobie and Circe: The Functional Web StackHttp4s, Doobie and Circe: The Functional Web Stack
Http4s, Doobie and Circe: The Functional Web StackGaryCoady
 
The Expression Problem - Part 1
The Expression Problem - Part 1The Expression Problem - Part 1
The Expression Problem - Part 1Philip Schwarz
 
Sum and Product Types - The Fruit Salad & Fruit Snack Example - From F# to Ha...
Sum and Product Types -The Fruit Salad & Fruit Snack Example - From F# to Ha...Sum and Product Types -The Fruit Salad & Fruit Snack Example - From F# to Ha...
Sum and Product Types - The Fruit Salad & Fruit Snack Example - From F# to Ha...Philip Schwarz
 
Purely Functional Data Structures in Scala
Purely Functional Data Structures in ScalaPurely Functional Data Structures in Scala
Purely Functional Data Structures in ScalaVladimir Kostyukov
 
Capabilities for Resources and Effects
Capabilities for Resources and EffectsCapabilities for Resources and Effects
Capabilities for Resources and EffectsMartin Odersky
 
ZIO-Direct - Functional Scala 2022
ZIO-Direct - Functional Scala 2022ZIO-Direct - Functional Scala 2022
ZIO-Direct - Functional Scala 2022Alexander Ioffe
 
Implicit parameters, when to use them (or not)!
Implicit parameters, when to use them (or not)!Implicit parameters, when to use them (or not)!
Implicit parameters, when to use them (or not)!Julien Truffaut
 
Quicksort - a whistle-stop tour of the algorithm in five languages and four p...
Quicksort - a whistle-stop tour of the algorithm in five languages and four p...Quicksort - a whistle-stop tour of the algorithm in five languages and four p...
Quicksort - a whistle-stop tour of the algorithm in five languages and four p...Philip Schwarz
 
The Expression Problem - Part 2
The Expression Problem - Part 2The Expression Problem - Part 2
The Expression Problem - Part 2Philip Schwarz
 
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1Philip Schwarz
 

What's hot (20)

Sequence and Traverse - Part 1
Sequence and Traverse - Part 1Sequence and Traverse - Part 1
Sequence and Traverse - Part 1
 
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part ...
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part ...Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part ...
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part ...
 
The aggregate function - from sequential and parallel folds to parallel aggre...
The aggregate function - from sequential and parallel folds to parallel aggre...The aggregate function - from sequential and parallel folds to parallel aggre...
The aggregate function - from sequential and parallel folds to parallel aggre...
 
Kleisli Composition
Kleisli CompositionKleisli Composition
Kleisli Composition
 
Preparing for Scala 3
Preparing for Scala 3Preparing for Scala 3
Preparing for Scala 3
 
‘go-to’ general-purpose sequential collections - from Java To Scala
‘go-to’ general-purpose sequential collections -from Java To Scala‘go-to’ general-purpose sequential collections -from Java To Scala
‘go-to’ general-purpose sequential collections - from Java To Scala
 
Zio in real world
Zio in real worldZio in real world
Zio in real world
 
Sequence and Traverse - Part 2
Sequence and Traverse - Part 2Sequence and Traverse - Part 2
Sequence and Traverse - Part 2
 
Http4s, Doobie and Circe: The Functional Web Stack
Http4s, Doobie and Circe: The Functional Web StackHttp4s, Doobie and Circe: The Functional Web Stack
Http4s, Doobie and Circe: The Functional Web Stack
 
The Expression Problem - Part 1
The Expression Problem - Part 1The Expression Problem - Part 1
The Expression Problem - Part 1
 
Sum and Product Types - The Fruit Salad & Fruit Snack Example - From F# to Ha...
Sum and Product Types -The Fruit Salad & Fruit Snack Example - From F# to Ha...Sum and Product Types -The Fruit Salad & Fruit Snack Example - From F# to Ha...
Sum and Product Types - The Fruit Salad & Fruit Snack Example - From F# to Ha...
 
Purely Functional Data Structures in Scala
Purely Functional Data Structures in ScalaPurely Functional Data Structures in Scala
Purely Functional Data Structures in Scala
 
Capabilities for Resources and Effects
Capabilities for Resources and EffectsCapabilities for Resources and Effects
Capabilities for Resources and Effects
 
ZIO-Direct - Functional Scala 2022
ZIO-Direct - Functional Scala 2022ZIO-Direct - Functional Scala 2022
ZIO-Direct - Functional Scala 2022
 
Implicit parameters, when to use them (or not)!
Implicit parameters, when to use them (or not)!Implicit parameters, when to use them (or not)!
Implicit parameters, when to use them (or not)!
 
Quicksort - a whistle-stop tour of the algorithm in five languages and four p...
Quicksort - a whistle-stop tour of the algorithm in five languages and four p...Quicksort - a whistle-stop tour of the algorithm in five languages and four p...
Quicksort - a whistle-stop tour of the algorithm in five languages and four p...
 
The Expression Problem - Part 2
The Expression Problem - Part 2The Expression Problem - Part 2
The Expression Problem - Part 2
 
C Programming Unit-5
C Programming Unit-5C Programming Unit-5
C Programming Unit-5
 
ZIO Queue
ZIO QueueZIO Queue
ZIO Queue
 
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1
 

Similar to Functional Core and Imperative Shell - Game of Life Example - Haskell and Scala

Game of Life - Polyglot FP - Haskell, Scala, Unison - Part 2 - with minor cor...
Game of Life - Polyglot FP - Haskell, Scala, Unison - Part 2 - with minor cor...Game of Life - Polyglot FP - Haskell, Scala, Unison - Part 2 - with minor cor...
Game of Life - Polyglot FP - Haskell, Scala, Unison - Part 2 - with minor cor...Philip Schwarz
 
Byterun, a Python bytecode interpreter - Allison Kaptur at NYCPython
Byterun, a Python bytecode interpreter - Allison Kaptur at NYCPythonByterun, a Python bytecode interpreter - Allison Kaptur at NYCPython
Byterun, a Python bytecode interpreter - Allison Kaptur at NYCPythonakaptur
 
T3chFest 2016 - The polyglot programmer
T3chFest 2016 - The polyglot programmerT3chFest 2016 - The polyglot programmer
T3chFest 2016 - The polyglot programmerDavid Muñoz Díaz
 
Future vs. Monix Task
Future vs. Monix TaskFuture vs. Monix Task
Future vs. Monix TaskHermann Hueck
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with ClojureDmitry Buzdin
 
Modular Module Systems
Modular Module SystemsModular Module Systems
Modular Module Systemsleague
 
NetPonto - The Future Of C# - NetConf Edition
NetPonto - The Future Of C# - NetConf EditionNetPonto - The Future Of C# - NetConf Edition
NetPonto - The Future Of C# - NetConf EditionPaulo Morgado
 
Talk - Query monad
Talk - Query monad Talk - Query monad
Talk - Query monad Fabernovel
 
C cheat sheet for varsity (extreme edition)
C cheat sheet for varsity (extreme edition)C cheat sheet for varsity (extreme edition)
C cheat sheet for varsity (extreme edition)Saifur Rahman
 
A Few of My Favorite (Python) Things
A Few of My Favorite (Python) ThingsA Few of My Favorite (Python) Things
A Few of My Favorite (Python) ThingsMichael Pirnat
 
An Intro To ES6
An Intro To ES6An Intro To ES6
An Intro To ES6FITC
 
Clojure Intro
Clojure IntroClojure Intro
Clojure Introthnetos
 
Kotlin For Android - Functions (part 3 of 7)
Kotlin For Android - Functions (part 3 of 7)Kotlin For Android - Functions (part 3 of 7)
Kotlin For Android - Functions (part 3 of 7)Gesh Markov
 
ES6 and AngularAMD
ES6 and AngularAMDES6 and AngularAMD
ES6 and AngularAMDdhaval10690
 

Similar to Functional Core and Imperative Shell - Game of Life Example - Haskell and Scala (20)

Game of Life - Polyglot FP - Haskell, Scala, Unison - Part 2 - with minor cor...
Game of Life - Polyglot FP - Haskell, Scala, Unison - Part 2 - with minor cor...Game of Life - Polyglot FP - Haskell, Scala, Unison - Part 2 - with minor cor...
Game of Life - Polyglot FP - Haskell, Scala, Unison - Part 2 - with minor cor...
 
Byterun, a Python bytecode interpreter - Allison Kaptur at NYCPython
Byterun, a Python bytecode interpreter - Allison Kaptur at NYCPythonByterun, a Python bytecode interpreter - Allison Kaptur at NYCPython
Byterun, a Python bytecode interpreter - Allison Kaptur at NYCPython
 
T3chFest 2016 - The polyglot programmer
T3chFest 2016 - The polyglot programmerT3chFest 2016 - The polyglot programmer
T3chFest 2016 - The polyglot programmer
 
Future vs. Monix Task
Future vs. Monix TaskFuture vs. Monix Task
Future vs. Monix Task
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with Clojure
 
ES6: The future is now
ES6: The future is nowES6: The future is now
ES6: The future is now
 
Modular Module Systems
Modular Module SystemsModular Module Systems
Modular Module Systems
 
NetPonto - The Future Of C# - NetConf Edition
NetPonto - The Future Of C# - NetConf EditionNetPonto - The Future Of C# - NetConf Edition
NetPonto - The Future Of C# - NetConf Edition
 
Talk - Query monad
Talk - Query monad Talk - Query monad
Talk - Query monad
 
C cheat sheet for varsity (extreme edition)
C cheat sheet for varsity (extreme edition)C cheat sheet for varsity (extreme edition)
C cheat sheet for varsity (extreme edition)
 
A Few of My Favorite (Python) Things
A Few of My Favorite (Python) ThingsA Few of My Favorite (Python) Things
A Few of My Favorite (Python) Things
 
Javascript
JavascriptJavascript
Javascript
 
An Intro To ES6
An Intro To ES6An Intro To ES6
An Intro To ES6
 
Functional programming
Functional programmingFunctional programming
Functional programming
 
ECMAScript 6
ECMAScript 6ECMAScript 6
ECMAScript 6
 
Clojure Intro
Clojure IntroClojure Intro
Clojure Intro
 
Kotlin For Android - Functions (part 3 of 7)
Kotlin For Android - Functions (part 3 of 7)Kotlin For Android - Functions (part 3 of 7)
Kotlin For Android - Functions (part 3 of 7)
 
Stack
StackStack
Stack
 
ES6 and AngularAMD
ES6 and AngularAMDES6 and AngularAMD
ES6 and AngularAMD
 
Vcs23
Vcs23Vcs23
Vcs23
 

More from Philip Schwarz

Folding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesFolding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesPhilip Schwarz
 
Folding Cheat Sheet #3 - third in a series
Folding Cheat Sheet #3 - third in a seriesFolding Cheat Sheet #3 - third in a series
Folding Cheat Sheet #3 - third in a seriesPhilip Schwarz
 
Folding Cheat Sheet #2 - second in a series
Folding Cheat Sheet #2 - second in a seriesFolding Cheat Sheet #2 - second in a series
Folding Cheat Sheet #2 - second in a seriesPhilip Schwarz
 
Folding Cheat Sheet #1 - first in a series
Folding Cheat Sheet #1 - first in a seriesFolding Cheat Sheet #1 - first in a series
Folding Cheat Sheet #1 - first in a seriesPhilip Schwarz
 
Scala Left Fold Parallelisation - Three Approaches
Scala Left Fold Parallelisation- Three ApproachesScala Left Fold Parallelisation- Three Approaches
Scala Left Fold Parallelisation - Three ApproachesPhilip Schwarz
 
Tagless Final Encoding - Algebras and Interpreters and also Programs
Tagless Final Encoding - Algebras and Interpreters and also ProgramsTagless Final Encoding - Algebras and Interpreters and also Programs
Tagless Final Encoding - Algebras and Interpreters and also ProgramsPhilip Schwarz
 
Fusing Transformations of Strict Scala Collections with Views
Fusing Transformations of Strict Scala Collections with ViewsFusing Transformations of Strict Scala Collections with Views
Fusing Transformations of Strict Scala Collections with ViewsPhilip Schwarz
 
A sighting of traverse_ function in Practical FP in Scala
A sighting of traverse_ function in Practical FP in ScalaA sighting of traverse_ function in Practical FP in Scala
A sighting of traverse_ function in Practical FP in ScalaPhilip Schwarz
 
A sighting of traverseFilter and foldMap in Practical FP in Scala
A sighting of traverseFilter and foldMap in Practical FP in ScalaA sighting of traverseFilter and foldMap in Practical FP in Scala
A sighting of traverseFilter and foldMap in Practical FP in ScalaPhilip Schwarz
 
A sighting of sequence function in Practical FP in Scala
A sighting of sequence function in Practical FP in ScalaA sighting of sequence function in Practical FP in Scala
A sighting of sequence function in Practical FP in ScalaPhilip Schwarz
 
N-Queens Combinatorial Puzzle meets Cats
N-Queens Combinatorial Puzzle meets CatsN-Queens Combinatorial Puzzle meets Cats
N-Queens Combinatorial Puzzle meets CatsPhilip Schwarz
 
Kleisli composition, flatMap, join, map, unit - implementation and interrelat...
Kleisli composition, flatMap, join, map, unit - implementation and interrelat...Kleisli composition, flatMap, join, map, unit - implementation and interrelat...
Kleisli composition, flatMap, join, map, unit - implementation and interrelat...Philip Schwarz
 
Nat, List and Option Monoids - from scratch - Combining and Folding - an example
Nat, List and Option Monoids -from scratch -Combining and Folding -an exampleNat, List and Option Monoids -from scratch -Combining and Folding -an example
Nat, List and Option Monoids - from scratch - Combining and Folding - an examplePhilip Schwarz
 
Nat, List and Option Monoids - from scratch - Combining and Folding - an example
Nat, List and Option Monoids -from scratch -Combining and Folding -an exampleNat, List and Option Monoids -from scratch -Combining and Folding -an example
Nat, List and Option Monoids - from scratch - Combining and Folding - an examplePhilip Schwarz
 
The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...
The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...
The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...Philip Schwarz
 
Jordan Peterson - The pursuit of meaning and related ethical axioms
Jordan Peterson - The pursuit of meaning and related ethical axiomsJordan Peterson - The pursuit of meaning and related ethical axioms
Jordan Peterson - The pursuit of meaning and related ethical axiomsPhilip Schwarz
 
Defining filter using (a) recursion (b) folding (c) folding with S, B and I c...
Defining filter using (a) recursion (b) folding (c) folding with S, B and I c...Defining filter using (a) recursion (b) folding (c) folding with S, B and I c...
Defining filter using (a) recursion (b) folding (c) folding with S, B and I c...Philip Schwarz
 
Defining filter using (a) recursion (b) folding with S, B and I combinators (...
Defining filter using (a) recursion (b) folding with S, B and I combinators (...Defining filter using (a) recursion (b) folding with S, B and I combinators (...
Defining filter using (a) recursion (b) folding with S, B and I combinators (...Philip Schwarz
 
The Sieve of Eratosthenes - Part 1 - with minor corrections
The Sieve of Eratosthenes - Part 1 - with minor correctionsThe Sieve of Eratosthenes - Part 1 - with minor corrections
The Sieve of Eratosthenes - Part 1 - with minor correctionsPhilip Schwarz
 
The Sieve of Eratosthenes - Part 1
The Sieve of Eratosthenes - Part 1The Sieve of Eratosthenes - Part 1
The Sieve of Eratosthenes - Part 1Philip Schwarz
 

More from Philip Schwarz (20)

Folding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesFolding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a series
 
Folding Cheat Sheet #3 - third in a series
Folding Cheat Sheet #3 - third in a seriesFolding Cheat Sheet #3 - third in a series
Folding Cheat Sheet #3 - third in a series
 
Folding Cheat Sheet #2 - second in a series
Folding Cheat Sheet #2 - second in a seriesFolding Cheat Sheet #2 - second in a series
Folding Cheat Sheet #2 - second in a series
 
Folding Cheat Sheet #1 - first in a series
Folding Cheat Sheet #1 - first in a seriesFolding Cheat Sheet #1 - first in a series
Folding Cheat Sheet #1 - first in a series
 
Scala Left Fold Parallelisation - Three Approaches
Scala Left Fold Parallelisation- Three ApproachesScala Left Fold Parallelisation- Three Approaches
Scala Left Fold Parallelisation - Three Approaches
 
Tagless Final Encoding - Algebras and Interpreters and also Programs
Tagless Final Encoding - Algebras and Interpreters and also ProgramsTagless Final Encoding - Algebras and Interpreters and also Programs
Tagless Final Encoding - Algebras and Interpreters and also Programs
 
Fusing Transformations of Strict Scala Collections with Views
Fusing Transformations of Strict Scala Collections with ViewsFusing Transformations of Strict Scala Collections with Views
Fusing Transformations of Strict Scala Collections with Views
 
A sighting of traverse_ function in Practical FP in Scala
A sighting of traverse_ function in Practical FP in ScalaA sighting of traverse_ function in Practical FP in Scala
A sighting of traverse_ function in Practical FP in Scala
 
A sighting of traverseFilter and foldMap in Practical FP in Scala
A sighting of traverseFilter and foldMap in Practical FP in ScalaA sighting of traverseFilter and foldMap in Practical FP in Scala
A sighting of traverseFilter and foldMap in Practical FP in Scala
 
A sighting of sequence function in Practical FP in Scala
A sighting of sequence function in Practical FP in ScalaA sighting of sequence function in Practical FP in Scala
A sighting of sequence function in Practical FP in Scala
 
N-Queens Combinatorial Puzzle meets Cats
N-Queens Combinatorial Puzzle meets CatsN-Queens Combinatorial Puzzle meets Cats
N-Queens Combinatorial Puzzle meets Cats
 
Kleisli composition, flatMap, join, map, unit - implementation and interrelat...
Kleisli composition, flatMap, join, map, unit - implementation and interrelat...Kleisli composition, flatMap, join, map, unit - implementation and interrelat...
Kleisli composition, flatMap, join, map, unit - implementation and interrelat...
 
Nat, List and Option Monoids - from scratch - Combining and Folding - an example
Nat, List and Option Monoids -from scratch -Combining and Folding -an exampleNat, List and Option Monoids -from scratch -Combining and Folding -an example
Nat, List and Option Monoids - from scratch - Combining and Folding - an example
 
Nat, List and Option Monoids - from scratch - Combining and Folding - an example
Nat, List and Option Monoids -from scratch -Combining and Folding -an exampleNat, List and Option Monoids -from scratch -Combining and Folding -an example
Nat, List and Option Monoids - from scratch - Combining and Folding - an example
 
The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...
The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...
The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...
 
Jordan Peterson - The pursuit of meaning and related ethical axioms
Jordan Peterson - The pursuit of meaning and related ethical axiomsJordan Peterson - The pursuit of meaning and related ethical axioms
Jordan Peterson - The pursuit of meaning and related ethical axioms
 
Defining filter using (a) recursion (b) folding (c) folding with S, B and I c...
Defining filter using (a) recursion (b) folding (c) folding with S, B and I c...Defining filter using (a) recursion (b) folding (c) folding with S, B and I c...
Defining filter using (a) recursion (b) folding (c) folding with S, B and I c...
 
Defining filter using (a) recursion (b) folding with S, B and I combinators (...
Defining filter using (a) recursion (b) folding with S, B and I combinators (...Defining filter using (a) recursion (b) folding with S, B and I combinators (...
Defining filter using (a) recursion (b) folding with S, B and I combinators (...
 
The Sieve of Eratosthenes - Part 1 - with minor corrections
The Sieve of Eratosthenes - Part 1 - with minor correctionsThe Sieve of Eratosthenes - Part 1 - with minor corrections
The Sieve of Eratosthenes - Part 1 - with minor corrections
 
The Sieve of Eratosthenes - Part 1
The Sieve of Eratosthenes - Part 1The Sieve of Eratosthenes - Part 1
The Sieve of Eratosthenes - Part 1
 

Recently uploaded

Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataAdobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataBradBedford3
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityNeo4j
 
What is Binary Language? Computer Number Systems
What is Binary Language?  Computer Number SystemsWhat is Binary Language?  Computer Number Systems
What is Binary Language? Computer Number SystemsJheuzeDellosa
 
Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...OnePlan Solutions
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxbodapatigopi8531
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providermohitmore19
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about usDynamic Netsoft
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEOrtus Solutions, Corp
 
chapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptchapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptkotipi9215
 
Engage Usergroup 2024 - The Good The Bad_The Ugly
Engage Usergroup 2024 - The Good The Bad_The UglyEngage Usergroup 2024 - The Good The Bad_The Ugly
Engage Usergroup 2024 - The Good The Bad_The UglyFrank van der Linden
 
Introduction to Decentralized Applications (dApps)
Introduction to Decentralized Applications (dApps)Introduction to Decentralized Applications (dApps)
Introduction to Decentralized Applications (dApps)Intelisync
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...MyIntelliSource, Inc.
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...stazi3110
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfkalichargn70th171
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...MyIntelliSource, Inc.
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Modelsaagamshah0812
 
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...soniya singh
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantAxelRicardoTrocheRiq
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfkalichargn70th171
 

Recently uploaded (20)

Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataAdobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered Sustainability
 
What is Binary Language? Computer Number Systems
What is Binary Language?  Computer Number SystemsWhat is Binary Language?  Computer Number Systems
What is Binary Language? Computer Number Systems
 
Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptx
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about us
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
 
Exploring iOS App Development: Simplifying the Process
Exploring iOS App Development: Simplifying the ProcessExploring iOS App Development: Simplifying the Process
Exploring iOS App Development: Simplifying the Process
 
chapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptchapter--4-software-project-planning.ppt
chapter--4-software-project-planning.ppt
 
Engage Usergroup 2024 - The Good The Bad_The Ugly
Engage Usergroup 2024 - The Good The Bad_The UglyEngage Usergroup 2024 - The Good The Bad_The Ugly
Engage Usergroup 2024 - The Good The Bad_The Ugly
 
Introduction to Decentralized Applications (dApps)
Introduction to Decentralized Applications (dApps)Introduction to Decentralized Applications (dApps)
Introduction to Decentralized Applications (dApps)
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
 
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service Consultant
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 

Functional Core and Imperative Shell - Game of Life Example - Haskell and Scala

  • 1. Functional Core and Imperative Shell Game of Life Example See a program structure flowchart used to highlight how an FP program breaks down into a functional core and imperative shell View a program structure flowchart for the Game of Life See the code for Game of Life’s functional core and imperative shell, both in Haskell and in Scala Polyglot FP for Fun and Profit – Haskell and Scala Graham Hutton @haskellhutt @VBragilevsky Vitaly Bragilevsky 𝜆 functional core imperative shell @philip_schwarz slides by https://www.slideshare.net/pjschwarz
  • 2. In Haskell in Depth, Vitaly Bragilevsky visualises certain aspects of his programs using program structure flowcharts. One of the things shown by his diagrams is how the programs break down into a pure part and an I/O part, i.e. into a functional core and an imperative shell. In this short slide deck we do the following: • create a program structure flowchart for the Game of Life • show how Game of Life code consists of a functional core and an imperative shell @philip_schwarz
  • 3. @VBragilevsky • User input is represented by parallelograms. • All functions are represented by rectangles. • Some of the functions are executing I/O actions. These are shown in the central part of the flowchart. • Other functions are pure. They are given on the right-hand side. • Diamonds traditionally represent choices made within a program. • Function calls are represented by rectangles below and to the right of a caller. • Several calls within a function are combined with a dashed line. • Arrows in this flowchart represent moving data between the user and the program and between functions within the program. READING A PROGRAM STRUCTURE FLOWCHART I’ve tried to present all the components of the program in a program structure flowchart: user input, actions in the I/O part of the program, and their relations with the pure functions. I use the following notation Vitaly Bragilevsky
  • 4. If you would like an introduction to the notion of ’functional core, imperative shell’, see slides 15-20 of the second slide deck below. If you want an explanation of the Game of Life code that we’ll be looking at next, see the first slide deck for Haskell, and the remaining two for Scala.
  • 5. OOO OOO O O O O O O O O O O O O OOO OOO OOO OOO O O O O O O O O O O O O OOO OOO O O O O OO OO OOO OO OO OOO O O O O O O OO OO OO OO O O O O O O OOO OO OO OOO OO OO O O O O OO OO OO OO O O O O O O OOO OO OO OOO O O O O O O OOO OOO OOO OOO O O O O O O OOO OO OO OOO O O O O O O OO OO OO OO If we run the upcoming Game of Life program with a 20 by 20 board configured with the first generation of a Pulsar, the program cycles forever through the following three patterns pulsar :: Board pulsar = [(4, 2),(5, 2),(6, 2),(10, 2),(11, 2),(12, 2), (2, 4),(7, 4),( 9, 4),(14, 4), (2, 5),(7, 5),( 9, 5),(14, 5), (2, 6),(7, 6),( 9, 6),(14, 6), (4, 7),(5, 7),(6, 7),(10, 7),(11, 7),(12, 7), (4, 9),(5, 9),(6, 9),(10, 9),(11, 9),(12, 9), (2,10),(7,10),( 9,10),(14,10), (2,11),(7,11),( 9,11),(14,11), (2,12),(7,12),( 9,12),(14,12), (4,14),(5,14),(6,14),(10,14),(11,14),(12,14)] type Pos = (Int,Int) width :: Int width = 20 type Board = [Pos] height :: Int height = 20
  • 6. The next slide shows a simple program structure flowchart for the Game of Life program. The rest of the slides show the following: 1. Haskell code for the program’s imperative shell 2. Haskell code for its functional core 3. .structure flowchart for the program (Scala version) 4. .Scala code for the imperative shell 5. .Scala code for the functional core The Haskell Game of Life code is the one found in Graham Hutton’s book, Programming in Haskell, with a handful of very minor changes, e.g. • added an extra invocation of a function in order to move the cursor out of the way after drawing a generation • added data for the first pulsar generation
  • 7. User Input I/O part Pure part main cls showcells nextgen life clears screen prints cells to screen wait main :: IO () main = life(pulsar) nextgen :: Board -> Board showcells :: Board -> IO () cls :: IO () wait :: Int -> IO () life :: Board -> IO () life b = do cls showcells b goto (width+1,height+1) wait 500000 life (nextgen b) FUNCTIONAL CORE IMPERATIVE SHELL goto moves cursor to bottom right goto :: Pos -> IO ()
  • 8. Graham Hutton @haskellhutt cls :: IO () cls = putStr "ESC[2J" showcells :: Board -> IO () showcells b = sequence_ [writeat p "O" | p <- b] wait :: Int -> IO () wait n = sequence_ [return () | _ <- [1..n]] main :: IO () main = life(pulsar) life :: Board -> IO () life b = do cls showcells b goto (width + 1, height + 1) wait 500000 life (nextgen b) writeat :: Pos -> String -> IO () writeat p xs = do goto p putStr xs goto :: Pos -> IO () goto (x,y) = putStr ("ESC[" ++ show y ++ ";" ++ show x ++ "H") putStr :: String -> IO () putStr [] = return () putStr (x:xs) = do putChar x putStr xs IMPERATIVE SHELL
  • 9. Graham Hutton @haskellhutt nextgen :: Board -> Board nextgen b = survivors b ++ births b survivors :: Board -> [Pos] survivors b = [p | p <- b, elem (liveneighbs b p) [2,3]] births :: Board -> [Pos] births b = [p | p <- rmdups (concat (map neighbs b)), isEmpty b p, liveneighbs b p == 3] neighbs :: Pos -> [Pos] neighbs (x,y) = map wrap [(x-1, y-1), (x, y-1), (x+1, y-1), (x-1, y ), (x+1, y), (x-1, y+1), (x, y+1), (x+1, y+1)] wrap :: Pos -> Pos wrap (x,y) = (((x-1) `mod` width) + 1, ((y-1) `mod` height) + 1) width :: Int height :: Int width = 20 height = 20 rmdups :: Eq a => [a] -> [a] rmdups [] = [] rmdups (x:xs) = x : rmdups (filter (/= x) xs) isEmpty :: Board -> Pos -> Bool isEmpty b p = not (isAlive b p) liveneighbs :: Board -> Pos -> Int liveneighbs b = length.filter(isAlive b).neighbs isAlive :: Board -> Pos -> Bool isAlive b p = elem p b pulsar :: Board pulsar = [(4, 2),(5, 2),(6, 2),(10, 2),(11, 2),(12, 2), (2, 4),(7, 4),( 9, 4),(14, 4), (2, 5),(7, 5),( 9, 5),(14, 5), (2, 6),(7, 6),( 9, 6),(14, 6), (4, 7),(5, 7),(6, 7),(10, 7),(11, 7),(12, 7), (4, 9),(5, 9),(6, 9),(10, 9),(11, 9),(12, 9), (2,10),(7,10),( 9,10),(14,10), (2,11),(7,11),( 9,11),(14,11), (2,12),(7,12),( 9,12),(14,12), (4,14),(5,14),(6,14),(10,14),(11,14),(12,14)] type Pos = (Int,Int) type Board = [Pos] FUNCTIONAL CORE
  • 10. User Input I/O part Pure part main cls showcells nextgen life clears screen prints cells to screen wait def nextgen(b:Board):Board FUNCTIONAL CORE IMPERATIVE SHELL goto moves cursor to bottom right def showCells(b: Board): IO[Unit] def cls: IO[Unit] def wait(n:Int): IO[Unit] def life(b: Board): IO[Unit] = cls *> showCells(b) *> goto(width+1,height+1) *> wait(1_000_000) >> life(nextgen(b)) val main: IO[Unit] = life(pulsar) def goto(p: Pos): IO[Unit]
  • 11. val main: IO[Unit] = life(pulsar) def life(b: Board): IO[Unit] = cls *> showCells(b) *> goto(width+1,height+1) *> wait(1_000_000) >> life(nextgen(b)) def cls: IO[Unit] = putStr("u001B[2J") def showCells(b: Board): IO[Unit] = ( for { p <- b } yield writeAt(p, "O") ).sequence_ def wait(n:Int): IO[Unit] = List.fill(n)(IO.unit).sequence_ def writeAt(p: Pos, s: String): IO[Unit] = goto(p) *> putStr(s) def goto(p: Pos): IO[Unit] = p match { case (x,y) => putStr(s"u001B[${y};${x}H") } def putStr(s: String): IO[Unit] = IO { scala.Predef.print(s) } IMPERATIVE SHELL import cats.implicits._, cats.effect.IO main.unsafeRunSync
  • 12. def nextgen(b: Board): Board = survivors(b) ++ births(b) def survivors(b: Board): List[Pos] = for { p <- b if List(2,3) contains liveneighbs(b)(p) } yield p def births(b: Board): List[Pos] = for { p <- rmdups(b flatMap neighbs) if isEmpty(b)(p) if liveneighbs(b)(p) == 3 } yield p def rmdups[A](l: List[A]): List[A] = l match { case Nil => Nil case x::xs => x::rmdups(xs filter(_ != x)) } def isEmpty(b: Board)(p: Pos): Boolean = !(isAlive(b)(p)) def liveneighbs(b: Board)(p: Pos): Int = neighbs(p).filter(isAlive(b)).length def isAlive(b: Board)(p: Pos): Boolean = b contains p def neighbs(p: Pos): List[Pos] = p match { case (x,y) => List( (x - 1, y - 1), (x, y - 1), (x + 1, y - 1), (x - 1, y ), /* cell */ (x + 1, y ), (x - 1, y + 1), (x, y + 1), (x + 1, y + 1) ) map wrap } def wrap(p: Pos): Pos = p match { case (x, y) => (((x - 1) % width) + 1, ((y - 1) % height) + 1) } val width = 20 val height = 20 val pulsar: Board = List( (4, 2),(5, 2),(6, 2),(10, 2),(11, 2),(12, 2), (2, 4),(7, 4),( 9, 4),(14, 4), (2, 5),(7, 5),( 9, 5),(14, 5), (2, 6),(7, 6),( 9, 6),(14, 6), (4, 7),(5, 7),(6, 7),(10, 7),(11, 7),(12, 7), (4, 9),(5, 9),(6, 9),(10, 9),(11, 9),(12, 9), (2,10),(7,10),( 9,10),(14,10), (2,11),(7,11),( 9,11),(14,11), (2,12),(7,12),( 9,12),(14,12), (4,14),(5,14),(6,14),(10,14),(11,14),(12,14)]) FUNCTIONAL CORE type Pos = (Int, Int) type Board = List[Pos]
  • 13. If you want to run the programs, you can find them here: • https://github.com/philipschwarz/functional-core-imperative-shell-scala • https://github.com/philipschwarz/functional-core-imperative-shell-haskell That’s all. I hope you found it useful. See you soon. @philip_schwarz