SlideShare a Scribd company logo
SUPERCHARGED IMPERATIVE
PROGRAMMING WITH HASKELL
AND FP
ANUPAM JAIN
2
Hello!
3
❑ HOME PAGE

https://fpncr.github.io
❑ GETTOGETHER COMMUNITY

https://gettogether.community/fpncr/
❑ MEETUP

https://www.meetup.com/DelhiNCR-Haskell-And-
Functional-Programming-Languages-Group
❑ TELEGRAM:

https://t.me/fpncr
Functional Programming NCR
4
❑Type safety. Eliminates a large class of errors.
❑Effectful values are first class
❑Higher Order Patterns
❑Reduction in Boilerplate
❑Zero Cost Code Reuse
Overview
5
❑Order of operations matters
❑Contrast with functional, where the order of
operations does not matter.
Define “Imperative”
6
write "Do you want a pizza?”
if (read() == "Yes") orderPizza()
write "Should I launch missiles?”
if (read() == "Yes") launchMissiles()
Imperative is simple
7
write "Do you want a pizza?”
if (read() == "Yes") orderPizza()
write "Should I launch missiles?”
if (read() == "Yes") launchMissiles()
Imperative is simple
You REALLY DON’T
want to do these
out of order
8
do
write "Do you want a pizza?"
canOrder <- read
When (canOrder == "Yes") orderPizza
write "Should I launch missiles?"
canLaunch <- read
When (canLaunch == "Yes") launchMissiles
Functional?
9
do
write "Do you want a pizza?"
canOrder <- read
when (canOrder == "Yes") orderPizza
write "Should I launch missiles?"
canLaunch <- read
when (canLaunch == "Yes") launchMissiles
Functional?
Haskell
10
write "Do you want a pizza?" >>= _ ->
read >>= canOrderPizza ->
if (canOrderPizza == "Yes") then
orderPizza
else pure () >>= _ ->
write "Should I launch missiles?" >>= _ -
>
read >>= canLaunchMissiles ->
if (canLaunchMissiles == "Yes") then
launchMissiles
else pure ()
Functional?
11
plusOne = x -> x+1
add = x -> y -> x+y
A bit of syntax
Lambdas
12
(>>=) = effect -> handler -> ...
A bit of syntax
Operators
13
read >>= canOrderPizza -> ...
A bit of syntax
Infix Usage
14
write "Do you want a pizza?" >>= _ ->
read >>= canOrderPizza ->
if (canOrderPizza == "Yes") then
orderPizza
else pure ()
One At a Time
15
write "Should I launch missiles?" >>= _ ->
read >>= canLaunchMissiles ->
if (canLaunchMissiles == "Yes") then
launchMissiles
else pure ()
One At a Time
16
handlePizza >>= _ ->
handleMissiles
Together
17
handlePizza >>= _ ->
handleMissiles
Together
18
handlePizza :: IO ()
handlePizza = do
write "Do you want a pizza?"
canOrderPizza <- read
if (canOrderPizza == "Yes")
then orderPizza
else pure ()
Types This entire block
1. Is Effectful
2. Returns ()
19
Effectful Logic
Pure Logic
Outside World
20
❑Can’t mix effectful (imperative) code with pure
(functional) code
❑All branches must have the same return type
Types
21
SideEffects!!
22
“Haskell” is the world’s finest
imperative programming
language.
~Simon Peyton Jones
(Creator of Haskell)
23
So How is Haskell
The Best Imperative
Programming
Language?
24
❑We don’t launch nukes without ordering pizza
Change Requirements
25
handlePizza :: IO Bool
handlePizza = do
write "Do you want a pizza?"
canOrderPizza <- read
if (canOrderPizza == "Yes")
then orderPizza >> pure true
else pure false
Types
26
do
pizzaOrdered <- handlePizza
if pizzaOrdered
then handleMissiles
else pure ()
With Changed
Requirements
27
❑Ask the user a bunch of questions
❑Then perform a bunch of actions
Reorder?
28
Must Rearchitect
do
write "Do you want a pizza?"
canOrder <- read
write "Should I launch missiles?"
canLaunch <- read
when (canOrder == "Yes") orderPizza
when (canLaunch == "Yes") launchMissiles
29
Must Rearchitect
do
write "Do you want a pizza?"
canOrder <- read
write "Should I launch missiles?"
canLaunch <- read
when (canOrder == "Yes") orderPizza
when (canLaunch == "Yes") launchMissiles
But we have lost
the separation
between
Ordering pizza
and Launching nukes
30
We Need
❑Define complex flows with user input and a final
effect to be performed
❑To compose these flows without boilerplate
❑Be able to run the final effects together at the end
of all user input
31
Desired Abstraction
handlePizza = ...
handleNukes = ...
do
handlePizza
handleNukes
We ask questions in this order,
but the final effect of ordering pizza
and launching nukes should only
happen together at the end
32
Must Rearchitect
handlePizza = do
write "Do you want a pizza?"
canOrder <- read
return $
when (canOrder == "Yes") orderPizza
33
Must Rearchitect
handlePizza :: IO (IO ())
handlePizza = do
write "Do you want a pizza?"
canOrder <- read
return $
when (canOrder == "Yes") orderPizza
Return value is a CLOSURE
Captures `canOrder`
34
Must Rearchitect
handleNukes :: IO (IO ())
handleNukes = do
write “Should I launch nukes?"
canLaunch <- read
return $
when (canLaunch == "Yes") launchNukes
Return value is a CLOSURE
Captures `canLaunch`
35
Compose together
do
pizzaEffect <- handlePizza
nukeEffect <- handleNukes
pizzaEffect

nukeEffect
36
Generalises?
This looks very boilerplaty
do
pizzaEffect <- handlePizza
nukeEffect <- handleNukes
...
pizzaEffect

nukeEffect
...
37
Desired Interface
finalEffect =

handlePizza AND

handleNukes AND
...
38
And Allow A Way to
specify “No Effects”
finalEffect = emptyEffects
39
Looks Like a Monoid!
class Monoid M where
empty :: M

(<>) :: M -> M -> M
40
IO already is a
Monoid!
❑What happens when we do the following?
handlePizza <> handleNukes
41
IO already is a
Monoid!
instance Monoid a => Monoid (IO a) where
empty = pure empty
f <> g = do
a <- f
b <- g
pure (a <> b)
42
IO already is a
Monoid!
instance Monoid a => Monoid (IO a) where
empty = pure empty
f <> g = do
a <- f
b <- g
pure (a <> b)
First perform individual effects
43
IO already is a
Monoid!
instance Monoid a => Monoid (IO a) where
empty = pure empty
f <> g = do
a <- f
b <- g
pure (a <> b) Then Join the results
As Monoids
44
IO already is a
Monoid!
❑So this does the right thing!
do
finalEffects <- handlePizza <> handleNukes
finalEffects
45
This is also a pattern
join :: Monad M => M (M a) -> M a
join :: IO (IO a) -> IO a
join (handlePizza <> handleNukes)
46
No Boilerplate!
join :: Monad M => M (M a) -> M a
join :: IO (IO a) -> IO a
join (handlePizza <> handleNukes)
47
Final Code

handlePizza
handlePizza :: IO (IO ())
handlePizza = do
write "Do you want a pizza?"
canOrder <- read
return $
when (canOrder == "Yes") orderPizza
48
Final Code

handleNukes
handleNukes :: IO (IO ())
handleNukes = do
write “Should I launch nukes?"
canLaunch <- read
return $
when (canLaunch == "Yes") launchNukes
49
Final Code

Combine flows together
join (handlePizza <> handleNukes <> ...)
join (mappend [ handlePizza
, handleNukes
...
])
Or Perhaps
50
❑We don’t launch nukes without ordering pizza
❑We don’t order pizza when not launching nukes
Change Requirements
Again
51
Must Rearchitect
do
write "Do you want a pizza?"
canOrder <- read
write "Should I launch missiles?"
canLaunch <- read
when (canOrder == “Yes" && canLaunch ==
"Yes") (orderPizza >> launchMissiles)
52
Must Rearchitect
do
write "Do you want a pizza?"
canOrder <- read
write "Should I launch missiles?"
canLaunch <- read
when (canOrder == “Yes" && canLaunch ==
"Yes") (orderPizza >> launchMissiles)
Business Logic
53
A General Pattern
do
write “Question 1 ...”
answer1 <- read
...
when (validates answer1 ...)
performAllEffects
54
We Need
❑Define complex flows with user input and a final
effect to be performed
❑To compose these flows without boilerplate
❑Call a function on all the user input to determine if
we should perform the final effects.
❑Be able to run the final effects together at the end
of all user input
55
Can we do this with
Monoids?
do
finalEffects <- handlePizza <> handleNukes
finalEffects
❑We abstracted away the captured variables
❑Now all we can do is run the final composed effect
We can’t access `canOrder` or `canLaunch` here
56
FP Gives you
Granularly
Powerful
Abstractions
❑Monads are too powerful (i.e. boilerplate)
❑Monoids abstract away too much
❑Need something in the middle
57
Let's work through this
data Ret a = Ret
{ input :: a
, effect :: IO ()
}
❑Return the final effect, AND the user input
❑Parameterise User Input as `a`
58
Let's work through this
handlePizza :: IO (Ret Boolean)
handlePizza = do
write "Do you want a pizza?"
canOrder <- read
return $ Ret canOrder $
when (canOrder == "Yes") orderPizza
59
Compose Effects
do
retPizza <- handlePizza
retNuke <- handleNuke
when valid (input retPizza) (input
retNuke) do
effect retPizza
effect retNuke
60
Compose Effects
do
retPizza <- handlePizza
retNuke <- handleNuke
when valid (input retPizza) (input
retNuke) do
effect retPizza
effect retNuke
UGH! Boilerplate!
61
Compose Effects
do
retPizza <- handlePizza
retNuke <- handleNuke
let go = valid (input retPizza) (input
retNuke)
when go do
effect retPizza
effect retNuke
62
Compose Effects
do
retPizza <- handlePizza
retNuke <- handleNuke
let go = valid (input retPizza) (input
retNuke)
when go do
effect retPizza
effect retNuke
Applicative!
63
IO is an Applicative
instance Applicative IO where
f <*> a = do
f' <- f
a' <- a
pure (f' a')
64
Try to Use Applicative IO
do
go <- valid
<$> (input <$> handlePizza)
<*> (input <$> handleNuke)
when go do
effect ??retPizza
effect ??retNuke
65
Dial Back a Little
do
(retPizza, retNuke) <- (,)
<$> handlePizza
<*> handleNuke
let go = valid
<$> input retPizza
<*> input retNuke
when go do
effect retPizza
effect retNuke
66
Perhaps a try a
different abstraction
do
(retPizza, retNuke) <- (,)
<$> handlePizza
<*> handleNuke
let go = valid
<$> input retPizza
<*> input retNuke
when go do
effect retPizza
effect retNuke
This is a common pattern
Can we abstract this?
67
Running a Return value
data Ret a = Ret
{ input :: a
, effect :: IO ()}
runRet :: Ret Bool -> IO ()
runRet (Ret b e) = when b e
68
More trouble than its
worth?
do
(retPizza, retNuke) <- (,)
<$> handlePizza
<*> handleNuke
let go = valid
<$> input retPizza
<*> input retNuke
runRet ??? We need to Compose a Ret
To be able to run it
69
However!
do
(retPizza, retNuke) <- (,)
<$> handlePizza
<*> handleNuke
let go = valid
<$> input retPizza
<*> input retNuke
runRet ???
This could return a
Ret instead!
70
Combining Return values
data Ret a = Ret
{ input :: a
, effect :: IO ()}
instance Functor Ret where
fmap f (Ret a e) = Ret (f a) e
instance Applicative Ret where
Ret f e1 <*> Ret a e2 =
Ret (f a) (e1 <> e2)
71
Less Boilerplate!
do
(retPizza, retNuke) <- (,)
<$> handlePizza
<*> handleNuke
let ret = valid
<$> retPizza
<*> retNuke
runRet ret
72
Hmm, Still Boilerplatey
do
(retPizza, retNuke) <- (,)
<$> handlePizza
<*> handleNuke
let ret = valid
<$> retPizza
<*> retNuke
runRet ret
Two Successive
Applicatives
73
Hmm, Still Boilerplatey
do
(retPizza, retNuke) <- (,)
<$> handlePizza
<*> handleNuke
let ret = valid
<$> retPizza
<*> retNuke
runRet ret
Combine Effectful

IO
Combine Effectful

Ret
74
Compose Applicatives?
data IO a = ...
data Ret a = Ret
{ input :: a
, effect :: IO ()}
type Flow a = IO (Ret a)
We need an Applicative instance for Flow
75
Applicatives Compose!
Import Data.Functor.Compose
type Compose f g a = Compose (f (g a))
type Flow a = Compose IO Ret a
76
Applicatives Compose!
instance (Applicative f, Applicative g)
=> Applicative (Compose f g) where
Compose f <*> Compose x =
Compose (liftA2 (<*>) f x)
77
Running Compose
runRet :: Ret Bool -> IO ()
runRet (Ret b e) = when b e
runFlow :: Compose IO Ret Bool -> IO ()
runFlow (Compose e) = e >>= runRet
78
Defining Flows
handlePizza :: Flow Boolean
handlePizza = Compose $ do
write "Do you want a pizza?"
canOrder <- read
return $ Ret canOrder $
when (canOrder == "Yes") orderPizza
79
Composing Flow With
Business Logic
valid
<$> handlePizza
<*> handleNukes
<*> ...
80
No Boilerplate
runFlow $ valid
<$> handlePizza
<*> handleNuke
81
❑Type safety. Eliminates a large class of errors.
❑Effectful values are first class
❑Higher Order Patterns
❑Reduction in Boilerplate
❑Zero Cost Code Reuse
Takeaways
82
SideEffects!!
83
Besties!!
84
Thank You
Questions?
Ad

Recommended

UI Dev in Big data world using open source
UI Dev in Big data world using open source
Tech Triveni
 
Why should a Java programmer shifts towards Functional Programming Paradigm
Why should a Java programmer shifts towards Functional Programming Paradigm
Tech Triveni
 
Reactive - Is it really a Magic Pill?
Reactive - Is it really a Magic Pill?
Tech Triveni
 
Let’s go reactive with JAVA
Let’s go reactive with JAVA
Tech Triveni
 
Tackling Asynchrony with Kotlin Coroutines
Tackling Asynchrony with Kotlin Coroutines
Tech Triveni
 
Programmatic Ad Tracking: Let the power of Reactive Microservices do talking
Programmatic Ad Tracking: Let the power of Reactive Microservices do talking
Tech Triveni
 
Let's refine your Scala Code
Let's refine your Scala Code
Tech Triveni
 
Observability at scale with Neural Networks: A more proactive approach
Observability at scale with Neural Networks: A more proactive approach
Tech Triveni
 
Semi-Supervised Insight Generation from Petabyte Scale Text Data
Semi-Supervised Insight Generation from Petabyte Scale Text Data
Tech Triveni
 
Finding the best solution for Image Processing
Finding the best solution for Image Processing
Tech Triveni
 
Proximity Targeting at Scale using Big Data Platforms
Proximity Targeting at Scale using Big Data Platforms
Tech Triveni
 
Effecting Pure Change - How anything ever gets done in functional programming...
Effecting Pure Change - How anything ever gets done in functional programming...
Tech Triveni
 
Becoming a Functional Programmer - Harit Himanshu (Nomis Solutions)
Becoming a Functional Programmer - Harit Himanshu (Nomis Solutions)
Tech Triveni
 
Live coding session on AI / ML using Google Tensorflow (Python) - Tanmoy Deb ...
Live coding session on AI / ML using Google Tensorflow (Python) - Tanmoy Deb ...
Tech Triveni
 
Distributing the SMACK stack - Kubernetes VS DCOS - Sahil Sawhney (Knoldus Inc.)
Distributing the SMACK stack - Kubernetes VS DCOS - Sahil Sawhney (Knoldus Inc.)
Tech Triveni
 
Blue Pill / Red Pill : The Matrix of thousands of data streams - Himanshu Gup...
Blue Pill / Red Pill : The Matrix of thousands of data streams - Himanshu Gup...
Tech Triveni
 
UX in Big Data Analytics - Paramjit Jolly (Guavus)
UX in Big Data Analytics - Paramjit Jolly (Guavus)
Tech Triveni
 
Simplified Scala Monads And Transformation - Harmeet Singh (Knoldus Inc.)
Simplified Scala Monads And Transformation - Harmeet Singh (Knoldus Inc.)
Tech Triveni
 
Micro Frontends Architecture - Jitendra kumawat (Guavus)
Micro Frontends Architecture - Jitendra kumawat (Guavus)
Tech Triveni
 
Apache CarbonData+Spark to realize data convergence and Unified high performa...
Apache CarbonData+Spark to realize data convergence and Unified high performa...
Tech Triveni
 
Micro Frontends Architecture - Jitendra kumawat (Guavus)
Micro Frontends Architecture - Jitendra kumawat (Guavus)
Tech Triveni
 
Augmentation of bids for programmatic ad auctions @ real time with the power ...
Augmentation of bids for programmatic ad auctions @ real time with the power ...
Tech Triveni
 
Programmable Decision Tree @Scale for Programmatic Media Buying - Rohit Sriva...
Programmable Decision Tree @Scale for Programmatic Media Buying - Rohit Sriva...
Tech Triveni
 
“Why It’s Critical to Have an Integrated Development Methodology for Edge AI,...
“Why It’s Critical to Have an Integrated Development Methodology for Edge AI,...
Edge AI and Vision Alliance
 
Viral>Wondershare Filmora 14.5.18.12900 Crack Free Download
Viral>Wondershare Filmora 14.5.18.12900 Crack Free Download
Puppy jhon
 
“Key Requirements to Successfully Implement Generative AI in Edge Devices—Opt...
“Key Requirements to Successfully Implement Generative AI in Edge Devices—Opt...
Edge AI and Vision Alliance
 
No-Code Workflows for CAD & 3D Data: Scaling AI-Driven Infrastructure
No-Code Workflows for CAD & 3D Data: Scaling AI-Driven Infrastructure
Safe Software
 
FME for Distribution & Transmission Integrity Management Program (DIMP & TIMP)
FME for Distribution & Transmission Integrity Management Program (DIMP & TIMP)
Safe Software
 
Kubernetes Security Act Now Before It’s Too Late
Kubernetes Security Act Now Before It’s Too Late
Michael Furman
 
Raman Bhaumik - Passionate Tech Enthusiast
Raman Bhaumik - Passionate Tech Enthusiast
Raman Bhaumik
 

More Related Content

More from Tech Triveni (15)

Semi-Supervised Insight Generation from Petabyte Scale Text Data
Semi-Supervised Insight Generation from Petabyte Scale Text Data
Tech Triveni
 
Finding the best solution for Image Processing
Finding the best solution for Image Processing
Tech Triveni
 
Proximity Targeting at Scale using Big Data Platforms
Proximity Targeting at Scale using Big Data Platforms
Tech Triveni
 
Effecting Pure Change - How anything ever gets done in functional programming...
Effecting Pure Change - How anything ever gets done in functional programming...
Tech Triveni
 
Becoming a Functional Programmer - Harit Himanshu (Nomis Solutions)
Becoming a Functional Programmer - Harit Himanshu (Nomis Solutions)
Tech Triveni
 
Live coding session on AI / ML using Google Tensorflow (Python) - Tanmoy Deb ...
Live coding session on AI / ML using Google Tensorflow (Python) - Tanmoy Deb ...
Tech Triveni
 
Distributing the SMACK stack - Kubernetes VS DCOS - Sahil Sawhney (Knoldus Inc.)
Distributing the SMACK stack - Kubernetes VS DCOS - Sahil Sawhney (Knoldus Inc.)
Tech Triveni
 
Blue Pill / Red Pill : The Matrix of thousands of data streams - Himanshu Gup...
Blue Pill / Red Pill : The Matrix of thousands of data streams - Himanshu Gup...
Tech Triveni
 
UX in Big Data Analytics - Paramjit Jolly (Guavus)
UX in Big Data Analytics - Paramjit Jolly (Guavus)
Tech Triveni
 
Simplified Scala Monads And Transformation - Harmeet Singh (Knoldus Inc.)
Simplified Scala Monads And Transformation - Harmeet Singh (Knoldus Inc.)
Tech Triveni
 
Micro Frontends Architecture - Jitendra kumawat (Guavus)
Micro Frontends Architecture - Jitendra kumawat (Guavus)
Tech Triveni
 
Apache CarbonData+Spark to realize data convergence and Unified high performa...
Apache CarbonData+Spark to realize data convergence and Unified high performa...
Tech Triveni
 
Micro Frontends Architecture - Jitendra kumawat (Guavus)
Micro Frontends Architecture - Jitendra kumawat (Guavus)
Tech Triveni
 
Augmentation of bids for programmatic ad auctions @ real time with the power ...
Augmentation of bids for programmatic ad auctions @ real time with the power ...
Tech Triveni
 
Programmable Decision Tree @Scale for Programmatic Media Buying - Rohit Sriva...
Programmable Decision Tree @Scale for Programmatic Media Buying - Rohit Sriva...
Tech Triveni
 
Semi-Supervised Insight Generation from Petabyte Scale Text Data
Semi-Supervised Insight Generation from Petabyte Scale Text Data
Tech Triveni
 
Finding the best solution for Image Processing
Finding the best solution for Image Processing
Tech Triveni
 
Proximity Targeting at Scale using Big Data Platforms
Proximity Targeting at Scale using Big Data Platforms
Tech Triveni
 
Effecting Pure Change - How anything ever gets done in functional programming...
Effecting Pure Change - How anything ever gets done in functional programming...
Tech Triveni
 
Becoming a Functional Programmer - Harit Himanshu (Nomis Solutions)
Becoming a Functional Programmer - Harit Himanshu (Nomis Solutions)
Tech Triveni
 
Live coding session on AI / ML using Google Tensorflow (Python) - Tanmoy Deb ...
Live coding session on AI / ML using Google Tensorflow (Python) - Tanmoy Deb ...
Tech Triveni
 
Distributing the SMACK stack - Kubernetes VS DCOS - Sahil Sawhney (Knoldus Inc.)
Distributing the SMACK stack - Kubernetes VS DCOS - Sahil Sawhney (Knoldus Inc.)
Tech Triveni
 
Blue Pill / Red Pill : The Matrix of thousands of data streams - Himanshu Gup...
Blue Pill / Red Pill : The Matrix of thousands of data streams - Himanshu Gup...
Tech Triveni
 
UX in Big Data Analytics - Paramjit Jolly (Guavus)
UX in Big Data Analytics - Paramjit Jolly (Guavus)
Tech Triveni
 
Simplified Scala Monads And Transformation - Harmeet Singh (Knoldus Inc.)
Simplified Scala Monads And Transformation - Harmeet Singh (Knoldus Inc.)
Tech Triveni
 
Micro Frontends Architecture - Jitendra kumawat (Guavus)
Micro Frontends Architecture - Jitendra kumawat (Guavus)
Tech Triveni
 
Apache CarbonData+Spark to realize data convergence and Unified high performa...
Apache CarbonData+Spark to realize data convergence and Unified high performa...
Tech Triveni
 
Micro Frontends Architecture - Jitendra kumawat (Guavus)
Micro Frontends Architecture - Jitendra kumawat (Guavus)
Tech Triveni
 
Augmentation of bids for programmatic ad auctions @ real time with the power ...
Augmentation of bids for programmatic ad auctions @ real time with the power ...
Tech Triveni
 
Programmable Decision Tree @Scale for Programmatic Media Buying - Rohit Sriva...
Programmable Decision Tree @Scale for Programmatic Media Buying - Rohit Sriva...
Tech Triveni
 

Recently uploaded (20)

“Why It’s Critical to Have an Integrated Development Methodology for Edge AI,...
“Why It’s Critical to Have an Integrated Development Methodology for Edge AI,...
Edge AI and Vision Alliance
 
Viral>Wondershare Filmora 14.5.18.12900 Crack Free Download
Viral>Wondershare Filmora 14.5.18.12900 Crack Free Download
Puppy jhon
 
“Key Requirements to Successfully Implement Generative AI in Edge Devices—Opt...
“Key Requirements to Successfully Implement Generative AI in Edge Devices—Opt...
Edge AI and Vision Alliance
 
No-Code Workflows for CAD & 3D Data: Scaling AI-Driven Infrastructure
No-Code Workflows for CAD & 3D Data: Scaling AI-Driven Infrastructure
Safe Software
 
FME for Distribution & Transmission Integrity Management Program (DIMP & TIMP)
FME for Distribution & Transmission Integrity Management Program (DIMP & TIMP)
Safe Software
 
Kubernetes Security Act Now Before It’s Too Late
Kubernetes Security Act Now Before It’s Too Late
Michael Furman
 
Raman Bhaumik - Passionate Tech Enthusiast
Raman Bhaumik - Passionate Tech Enthusiast
Raman Bhaumik
 
FIDO Seminar: Authentication for a Billion Consumers - Amazon.pptx
FIDO Seminar: Authentication for a Billion Consumers - Amazon.pptx
FIDO Alliance
 
FIDO Seminar: Targeting Trust: The Future of Identity in the Workforce.pptx
FIDO Seminar: Targeting Trust: The Future of Identity in the Workforce.pptx
FIDO Alliance
 
AI VIDEO MAGAZINE - June 2025 - r/aivideo
AI VIDEO MAGAZINE - June 2025 - r/aivideo
1pcity Studios, Inc
 
ENERGY CONSUMPTION CALCULATION IN ENERGY-EFFICIENT AIR CONDITIONER.pdf
ENERGY CONSUMPTION CALCULATION IN ENERGY-EFFICIENT AIR CONDITIONER.pdf
Muhammad Rizwan Akram
 
Edge-banding-machines-edgeteq-s-200-en-.pdf
Edge-banding-machines-edgeteq-s-200-en-.pdf
AmirStern2
 
AI vs Human Writing: Can You Tell the Difference?
AI vs Human Writing: Can You Tell the Difference?
Shashi Sathyanarayana, Ph.D
 
June Patch Tuesday
June Patch Tuesday
Ivanti
 
“Addressing Evolving AI Model Challenges Through Memory and Storage,” a Prese...
“Addressing Evolving AI Model Challenges Through Memory and Storage,” a Prese...
Edge AI and Vision Alliance
 
TrustArc Webinar - 2025 Global Privacy Survey
TrustArc Webinar - 2025 Global Privacy Survey
TrustArc
 
Reducing Conflicts and Increasing Safety Along the Cycling Networks of East-F...
Reducing Conflicts and Increasing Safety Along the Cycling Networks of East-F...
Safe Software
 
OWASP Barcelona 2025 Threat Model Library
OWASP Barcelona 2025 Threat Model Library
PetraVukmirovic
 
Artificial Intelligence in the Nonprofit Boardroom.pdf
Artificial Intelligence in the Nonprofit Boardroom.pdf
OnBoard
 
FIDO Seminar: Perspectives on Passkeys & Consumer Adoption.pptx
FIDO Seminar: Perspectives on Passkeys & Consumer Adoption.pptx
FIDO Alliance
 
“Why It’s Critical to Have an Integrated Development Methodology for Edge AI,...
“Why It’s Critical to Have an Integrated Development Methodology for Edge AI,...
Edge AI and Vision Alliance
 
Viral>Wondershare Filmora 14.5.18.12900 Crack Free Download
Viral>Wondershare Filmora 14.5.18.12900 Crack Free Download
Puppy jhon
 
“Key Requirements to Successfully Implement Generative AI in Edge Devices—Opt...
“Key Requirements to Successfully Implement Generative AI in Edge Devices—Opt...
Edge AI and Vision Alliance
 
No-Code Workflows for CAD & 3D Data: Scaling AI-Driven Infrastructure
No-Code Workflows for CAD & 3D Data: Scaling AI-Driven Infrastructure
Safe Software
 
FME for Distribution & Transmission Integrity Management Program (DIMP & TIMP)
FME for Distribution & Transmission Integrity Management Program (DIMP & TIMP)
Safe Software
 
Kubernetes Security Act Now Before It’s Too Late
Kubernetes Security Act Now Before It’s Too Late
Michael Furman
 
Raman Bhaumik - Passionate Tech Enthusiast
Raman Bhaumik - Passionate Tech Enthusiast
Raman Bhaumik
 
FIDO Seminar: Authentication for a Billion Consumers - Amazon.pptx
FIDO Seminar: Authentication for a Billion Consumers - Amazon.pptx
FIDO Alliance
 
FIDO Seminar: Targeting Trust: The Future of Identity in the Workforce.pptx
FIDO Seminar: Targeting Trust: The Future of Identity in the Workforce.pptx
FIDO Alliance
 
AI VIDEO MAGAZINE - June 2025 - r/aivideo
AI VIDEO MAGAZINE - June 2025 - r/aivideo
1pcity Studios, Inc
 
ENERGY CONSUMPTION CALCULATION IN ENERGY-EFFICIENT AIR CONDITIONER.pdf
ENERGY CONSUMPTION CALCULATION IN ENERGY-EFFICIENT AIR CONDITIONER.pdf
Muhammad Rizwan Akram
 
Edge-banding-machines-edgeteq-s-200-en-.pdf
Edge-banding-machines-edgeteq-s-200-en-.pdf
AmirStern2
 
AI vs Human Writing: Can You Tell the Difference?
AI vs Human Writing: Can You Tell the Difference?
Shashi Sathyanarayana, Ph.D
 
June Patch Tuesday
June Patch Tuesday
Ivanti
 
“Addressing Evolving AI Model Challenges Through Memory and Storage,” a Prese...
“Addressing Evolving AI Model Challenges Through Memory and Storage,” a Prese...
Edge AI and Vision Alliance
 
TrustArc Webinar - 2025 Global Privacy Survey
TrustArc Webinar - 2025 Global Privacy Survey
TrustArc
 
Reducing Conflicts and Increasing Safety Along the Cycling Networks of East-F...
Reducing Conflicts and Increasing Safety Along the Cycling Networks of East-F...
Safe Software
 
OWASP Barcelona 2025 Threat Model Library
OWASP Barcelona 2025 Threat Model Library
PetraVukmirovic
 
Artificial Intelligence in the Nonprofit Boardroom.pdf
Artificial Intelligence in the Nonprofit Boardroom.pdf
OnBoard
 
FIDO Seminar: Perspectives on Passkeys & Consumer Adoption.pptx
FIDO Seminar: Perspectives on Passkeys & Consumer Adoption.pptx
FIDO Alliance
 
Ad

Supercharged imperative programming with Haskell and Functional Programming

  • 1. SUPERCHARGED IMPERATIVE PROGRAMMING WITH HASKELL AND FP ANUPAM JAIN
  • 3. 3 ❑ HOME PAGE
 https://fpncr.github.io ❑ GETTOGETHER COMMUNITY
 https://gettogether.community/fpncr/ ❑ MEETUP
 https://www.meetup.com/DelhiNCR-Haskell-And- Functional-Programming-Languages-Group ❑ TELEGRAM:
 https://t.me/fpncr Functional Programming NCR
  • 4. 4 ❑Type safety. Eliminates a large class of errors. ❑Effectful values are first class ❑Higher Order Patterns ❑Reduction in Boilerplate ❑Zero Cost Code Reuse Overview
  • 5. 5 ❑Order of operations matters ❑Contrast with functional, where the order of operations does not matter. Define “Imperative”
  • 6. 6 write "Do you want a pizza?” if (read() == "Yes") orderPizza() write "Should I launch missiles?” if (read() == "Yes") launchMissiles() Imperative is simple
  • 7. 7 write "Do you want a pizza?” if (read() == "Yes") orderPizza() write "Should I launch missiles?” if (read() == "Yes") launchMissiles() Imperative is simple You REALLY DON’T want to do these out of order
  • 8. 8 do write "Do you want a pizza?" canOrder <- read When (canOrder == "Yes") orderPizza write "Should I launch missiles?" canLaunch <- read When (canLaunch == "Yes") launchMissiles Functional?
  • 9. 9 do write "Do you want a pizza?" canOrder <- read when (canOrder == "Yes") orderPizza write "Should I launch missiles?" canLaunch <- read when (canLaunch == "Yes") launchMissiles Functional? Haskell
  • 10. 10 write "Do you want a pizza?" >>= _ -> read >>= canOrderPizza -> if (canOrderPizza == "Yes") then orderPizza else pure () >>= _ -> write "Should I launch missiles?" >>= _ - > read >>= canLaunchMissiles -> if (canLaunchMissiles == "Yes") then launchMissiles else pure () Functional?
  • 11. 11 plusOne = x -> x+1 add = x -> y -> x+y A bit of syntax Lambdas
  • 12. 12 (>>=) = effect -> handler -> ... A bit of syntax Operators
  • 13. 13 read >>= canOrderPizza -> ... A bit of syntax Infix Usage
  • 14. 14 write "Do you want a pizza?" >>= _ -> read >>= canOrderPizza -> if (canOrderPizza == "Yes") then orderPizza else pure () One At a Time
  • 15. 15 write "Should I launch missiles?" >>= _ -> read >>= canLaunchMissiles -> if (canLaunchMissiles == "Yes") then launchMissiles else pure () One At a Time
  • 16. 16 handlePizza >>= _ -> handleMissiles Together
  • 17. 17 handlePizza >>= _ -> handleMissiles Together
  • 18. 18 handlePizza :: IO () handlePizza = do write "Do you want a pizza?" canOrderPizza <- read if (canOrderPizza == "Yes") then orderPizza else pure () Types This entire block 1. Is Effectful 2. Returns ()
  • 20. 20 ❑Can’t mix effectful (imperative) code with pure (functional) code ❑All branches must have the same return type Types
  • 22. 22 “Haskell” is the world’s finest imperative programming language. ~Simon Peyton Jones (Creator of Haskell)
  • 23. 23 So How is Haskell The Best Imperative Programming Language?
  • 24. 24 ❑We don’t launch nukes without ordering pizza Change Requirements
  • 25. 25 handlePizza :: IO Bool handlePizza = do write "Do you want a pizza?" canOrderPizza <- read if (canOrderPizza == "Yes") then orderPizza >> pure true else pure false Types
  • 26. 26 do pizzaOrdered <- handlePizza if pizzaOrdered then handleMissiles else pure () With Changed Requirements
  • 27. 27 ❑Ask the user a bunch of questions ❑Then perform a bunch of actions Reorder?
  • 28. 28 Must Rearchitect do write "Do you want a pizza?" canOrder <- read write "Should I launch missiles?" canLaunch <- read when (canOrder == "Yes") orderPizza when (canLaunch == "Yes") launchMissiles
  • 29. 29 Must Rearchitect do write "Do you want a pizza?" canOrder <- read write "Should I launch missiles?" canLaunch <- read when (canOrder == "Yes") orderPizza when (canLaunch == "Yes") launchMissiles But we have lost the separation between Ordering pizza and Launching nukes
  • 30. 30 We Need ❑Define complex flows with user input and a final effect to be performed ❑To compose these flows without boilerplate ❑Be able to run the final effects together at the end of all user input
  • 31. 31 Desired Abstraction handlePizza = ... handleNukes = ... do handlePizza handleNukes We ask questions in this order, but the final effect of ordering pizza and launching nukes should only happen together at the end
  • 32. 32 Must Rearchitect handlePizza = do write "Do you want a pizza?" canOrder <- read return $ when (canOrder == "Yes") orderPizza
  • 33. 33 Must Rearchitect handlePizza :: IO (IO ()) handlePizza = do write "Do you want a pizza?" canOrder <- read return $ when (canOrder == "Yes") orderPizza Return value is a CLOSURE Captures `canOrder`
  • 34. 34 Must Rearchitect handleNukes :: IO (IO ()) handleNukes = do write “Should I launch nukes?" canLaunch <- read return $ when (canLaunch == "Yes") launchNukes Return value is a CLOSURE Captures `canLaunch`
  • 35. 35 Compose together do pizzaEffect <- handlePizza nukeEffect <- handleNukes pizzaEffect
 nukeEffect
  • 36. 36 Generalises? This looks very boilerplaty do pizzaEffect <- handlePizza nukeEffect <- handleNukes ... pizzaEffect
 nukeEffect ...
  • 38. 38 And Allow A Way to specify “No Effects” finalEffect = emptyEffects
  • 39. 39 Looks Like a Monoid! class Monoid M where empty :: M
 (<>) :: M -> M -> M
  • 40. 40 IO already is a Monoid! ❑What happens when we do the following? handlePizza <> handleNukes
  • 41. 41 IO already is a Monoid! instance Monoid a => Monoid (IO a) where empty = pure empty f <> g = do a <- f b <- g pure (a <> b)
  • 42. 42 IO already is a Monoid! instance Monoid a => Monoid (IO a) where empty = pure empty f <> g = do a <- f b <- g pure (a <> b) First perform individual effects
  • 43. 43 IO already is a Monoid! instance Monoid a => Monoid (IO a) where empty = pure empty f <> g = do a <- f b <- g pure (a <> b) Then Join the results As Monoids
  • 44. 44 IO already is a Monoid! ❑So this does the right thing! do finalEffects <- handlePizza <> handleNukes finalEffects
  • 45. 45 This is also a pattern join :: Monad M => M (M a) -> M a join :: IO (IO a) -> IO a join (handlePizza <> handleNukes)
  • 46. 46 No Boilerplate! join :: Monad M => M (M a) -> M a join :: IO (IO a) -> IO a join (handlePizza <> handleNukes)
  • 47. 47 Final Code
 handlePizza handlePizza :: IO (IO ()) handlePizza = do write "Do you want a pizza?" canOrder <- read return $ when (canOrder == "Yes") orderPizza
  • 48. 48 Final Code
 handleNukes handleNukes :: IO (IO ()) handleNukes = do write “Should I launch nukes?" canLaunch <- read return $ when (canLaunch == "Yes") launchNukes
  • 49. 49 Final Code
 Combine flows together join (handlePizza <> handleNukes <> ...) join (mappend [ handlePizza , handleNukes ... ]) Or Perhaps
  • 50. 50 ❑We don’t launch nukes without ordering pizza ❑We don’t order pizza when not launching nukes Change Requirements Again
  • 51. 51 Must Rearchitect do write "Do you want a pizza?" canOrder <- read write "Should I launch missiles?" canLaunch <- read when (canOrder == “Yes" && canLaunch == "Yes") (orderPizza >> launchMissiles)
  • 52. 52 Must Rearchitect do write "Do you want a pizza?" canOrder <- read write "Should I launch missiles?" canLaunch <- read when (canOrder == “Yes" && canLaunch == "Yes") (orderPizza >> launchMissiles) Business Logic
  • 53. 53 A General Pattern do write “Question 1 ...” answer1 <- read ... when (validates answer1 ...) performAllEffects
  • 54. 54 We Need ❑Define complex flows with user input and a final effect to be performed ❑To compose these flows without boilerplate ❑Call a function on all the user input to determine if we should perform the final effects. ❑Be able to run the final effects together at the end of all user input
  • 55. 55 Can we do this with Monoids? do finalEffects <- handlePizza <> handleNukes finalEffects ❑We abstracted away the captured variables ❑Now all we can do is run the final composed effect We can’t access `canOrder` or `canLaunch` here
  • 56. 56 FP Gives you Granularly Powerful Abstractions ❑Monads are too powerful (i.e. boilerplate) ❑Monoids abstract away too much ❑Need something in the middle
  • 57. 57 Let's work through this data Ret a = Ret { input :: a , effect :: IO () } ❑Return the final effect, AND the user input ❑Parameterise User Input as `a`
  • 58. 58 Let's work through this handlePizza :: IO (Ret Boolean) handlePizza = do write "Do you want a pizza?" canOrder <- read return $ Ret canOrder $ when (canOrder == "Yes") orderPizza
  • 59. 59 Compose Effects do retPizza <- handlePizza retNuke <- handleNuke when valid (input retPizza) (input retNuke) do effect retPizza effect retNuke
  • 60. 60 Compose Effects do retPizza <- handlePizza retNuke <- handleNuke when valid (input retPizza) (input retNuke) do effect retPizza effect retNuke UGH! Boilerplate!
  • 61. 61 Compose Effects do retPizza <- handlePizza retNuke <- handleNuke let go = valid (input retPizza) (input retNuke) when go do effect retPizza effect retNuke
  • 62. 62 Compose Effects do retPizza <- handlePizza retNuke <- handleNuke let go = valid (input retPizza) (input retNuke) when go do effect retPizza effect retNuke Applicative!
  • 63. 63 IO is an Applicative instance Applicative IO where f <*> a = do f' <- f a' <- a pure (f' a')
  • 64. 64 Try to Use Applicative IO do go <- valid <$> (input <$> handlePizza) <*> (input <$> handleNuke) when go do effect ??retPizza effect ??retNuke
  • 65. 65 Dial Back a Little do (retPizza, retNuke) <- (,) <$> handlePizza <*> handleNuke let go = valid <$> input retPizza <*> input retNuke when go do effect retPizza effect retNuke
  • 66. 66 Perhaps a try a different abstraction do (retPizza, retNuke) <- (,) <$> handlePizza <*> handleNuke let go = valid <$> input retPizza <*> input retNuke when go do effect retPizza effect retNuke This is a common pattern Can we abstract this?
  • 67. 67 Running a Return value data Ret a = Ret { input :: a , effect :: IO ()} runRet :: Ret Bool -> IO () runRet (Ret b e) = when b e
  • 68. 68 More trouble than its worth? do (retPizza, retNuke) <- (,) <$> handlePizza <*> handleNuke let go = valid <$> input retPizza <*> input retNuke runRet ??? We need to Compose a Ret To be able to run it
  • 69. 69 However! do (retPizza, retNuke) <- (,) <$> handlePizza <*> handleNuke let go = valid <$> input retPizza <*> input retNuke runRet ??? This could return a Ret instead!
  • 70. 70 Combining Return values data Ret a = Ret { input :: a , effect :: IO ()} instance Functor Ret where fmap f (Ret a e) = Ret (f a) e instance Applicative Ret where Ret f e1 <*> Ret a e2 = Ret (f a) (e1 <> e2)
  • 71. 71 Less Boilerplate! do (retPizza, retNuke) <- (,) <$> handlePizza <*> handleNuke let ret = valid <$> retPizza <*> retNuke runRet ret
  • 72. 72 Hmm, Still Boilerplatey do (retPizza, retNuke) <- (,) <$> handlePizza <*> handleNuke let ret = valid <$> retPizza <*> retNuke runRet ret Two Successive Applicatives
  • 73. 73 Hmm, Still Boilerplatey do (retPizza, retNuke) <- (,) <$> handlePizza <*> handleNuke let ret = valid <$> retPizza <*> retNuke runRet ret Combine Effectful
 IO Combine Effectful
 Ret
  • 74. 74 Compose Applicatives? data IO a = ... data Ret a = Ret { input :: a , effect :: IO ()} type Flow a = IO (Ret a) We need an Applicative instance for Flow
  • 75. 75 Applicatives Compose! Import Data.Functor.Compose type Compose f g a = Compose (f (g a)) type Flow a = Compose IO Ret a
  • 76. 76 Applicatives Compose! instance (Applicative f, Applicative g) => Applicative (Compose f g) where Compose f <*> Compose x = Compose (liftA2 (<*>) f x)
  • 77. 77 Running Compose runRet :: Ret Bool -> IO () runRet (Ret b e) = when b e runFlow :: Compose IO Ret Bool -> IO () runFlow (Compose e) = e >>= runRet
  • 78. 78 Defining Flows handlePizza :: Flow Boolean handlePizza = Compose $ do write "Do you want a pizza?" canOrder <- read return $ Ret canOrder $ when (canOrder == "Yes") orderPizza
  • 79. 79 Composing Flow With Business Logic valid <$> handlePizza <*> handleNukes <*> ...
  • 80. 80 No Boilerplate runFlow $ valid <$> handlePizza <*> handleNuke
  • 81. 81 ❑Type safety. Eliminates a large class of errors. ❑Effectful values are first class ❑Higher Order Patterns ❑Reduction in Boilerplate ❑Zero Cost Code Reuse Takeaways