Monads in Ruby - Victor Zagorodny

Ruby Meditation
Ruby MeditationRuby Meditation
MONADS IN RUBY
BY VICTOR ZAGORODNY
Email: post.vittorius@gmail.com
Twitter: https://twitter.com/vittoriuz
Github: https://github.com/vittorius
Monads in Ruby - Victor Zagorodny
MONADS: WHAT IS IT?
Monads in Ruby - Victor Zagorodny
A monad is a monoid in the category of
endofunctors, what's the problem?
— James Iry
MONADS: WHAT IS IT?
MONADS: WHY?
LAZY EVALUATION
EXAMPLE #1 (PSEUDOCODE):
EXAMPLE #2:
let numbers = [1, ...]
fun is_prime x = all (map (y -> x mod y <> 0) [2..x-1])
let primes = filter is_prime numbers
let tenth_prime = first (take primes 10)
print tenth_prime
if user.signed_in? && user.current_order&.pending?
# ...
WELCOME TO THE FUTURE
f = Future.new do
# executed asynchronously
end
f.complete? # non-blocking
f.on_complete do |value|
# called upon completion; preferred approach
end
f.value # blocks until complete; less preferred approach
AN UGLY EXAMPLE
users = UsersService.all
archived_users = ArchivedUsersService.for_last_month
(users + archived_users).select(&:active?).size
FUNCTIONALLY BEAUTIFUL EXAMPLE
count(
only_active(
concat(
Future.new { UsersService.all },
Future.new { ArchivedUsersService.for_last_month }
)
)
)
FUNCTIONALLY BEAUTIFUL EXAMPLE
count_f(
only_active_f(
concat_f(
Future.new { UsersService.all },
Future.new { ArchivedUsersService.for_last_month }
)
)
)
INGREDIENTS: UNIT
(aka "bind", "return")
f = Future.new(x)
# or
f = Future.new
f.complete_with(x)
f.value # doesn't block
f.complete? # == true
class Future
# unit : Value -> Future<Value>
def self.unit(value)
Future.new(value)
end
end
INGREDIENTS: FMAP
# count_f : Future<Enumerable> -> Future<Integer>
def count_f(future)
future.fmap(
# f: Enumerable -> Integer
->(enumerable) { enumerable.count }
)
end
class Future
# ...
# fmap: Func<Value, Value> -> Future<Value>
def fmap(func)
f_new = Future.new
on_complete do |value|
f_new.complete_with(func.call(value))
end
f_new
end
end
INGREDIENTS: FMAP
# only_active_f : Future<Enumerable> -> Future<Enumerable>
def only_active_f(future)
future.fmap(
# f: Enumerable -> Enumerable
->(enumerable) { enumerable.select(&:active?) }
)
end
Monads in Ruby - Victor Zagorodny
CHAINING FUTURES
oops...
f = Future.new { UsersService.all }.fmap(
# f: Enumerable -> Future<Profile>
->(users) {
Future.new { ProfileService.profile_for(users.first) }
}
)
f.value # let's get the profile of a first user...
class Future
def fmap(func)
f_new = Future.new
on_complete do |value|
f_new.complete_with(func.call(value)) # it's a Future!
end
f_new
end
end
INGREDIENTS: FLATTEN
(aka "join")
class Future
# ...
protected
# flatten: Future<Future<Value>> -> Future<Value>
def flatten
f_flat = Future.new
on_complete do |f_internal|
f_internal.on_complete do |value|
f_flat.complete_with(value)
end
end
f_flat
end
end
INGREDIENTS: BIND
(aka "flatMap")
class Future
# ...
# bind: Func<Value, Future<Value>> -> Future<Value>
def bind(func)
fmap(func).flatten
end
end
CHAINING FUTURES CORRECTLY
f = Future.new { UsersService.all }.bind(
# f: Enumerable -> Future<Profile>
->(users) {
Future.new { ProfileService.profile_for(users.first) }
}
)
# fmap(func).flatten was called under the hood
f.value # now it's the Profile
TWO IMPORTANT THINGS
1. Future is a monad
Just believe me
2. I won't tell you how we built the concat_f
function
But I can give some clues
LIFTING
count -> lift -> count_f
def lift(func)
->(future) { future.fmap(func) }
end
concat -> lift2 -> concat_f
# Func<Value, Value, Value>
# -> Func<Future<Value>, <Future<Value>, <Future<Value>>
def lift2(func) # aka "liftM2"
# ...
end
MONAD: DEFINITION (AT LAST)
It's a data type
It's a container for some (immutable) value
It has a unit operation defined which wraps a
value in it
It has a bind operation defined which allows
building a chain of transformations over a monadic
value
All of these make monad a "programmable semicolon"
EXAMPLE: MAYBE MONAD
class Maybe
attr_reader :value
class Some < Maybe
def initialize(value)
@value = value
end
end
class None < Maybe; end
end
EXAMPLE: MAYBE MONAD
class Maybe
# "unit" function
def self.[](value)
value.nil? ? None.new : Some.new(value)
end
def bind(func)
is_a?(None) ? self : func.call(self.value)
end
alias_method :>=, :bind
end
EXAMPLE: MAYBE MONAD (USAGE)
# add_m2:
# Func<Maybe<Integer>, Maybe<Integer>> -> Maybe<Integer>
def add_m2(m1, m2)
m1.>=( # calling bind
->(x) { # in binding function; value of m1 unpacked to x
# we need to return Maybe from here; m2 is Maybe
# m2.>= will also return Maybe
m2.>=( # calling bind
->(y) { # value of m2 unpacked to y
Maybe[x + y] # x and y are Integers
# add them and wrap the result into Maybe
}
EXAMPLE: MAYBE MONAD (USAGE)
add_m2(Maybe[1], Maybe[2]) # => Maybe::Some#<value = 3>
add_m2(Maybe[4], Maybe[5]).value # => 9
add_m2(Maybe[nil], Maybe[5])
# => Maybe::None; "bind" of Maybe[5] was not executed
MAYBE MONAD
maybe_user = Maybe(user).bind do |u|
Maybe(u.address).bind do |a|
Maybe(a.street)
end
end
# If user with address exists
=> Some("Street Address")
# If user or address is nil
=> None()
EITHER MONAD
def calculate(input)
Right(input).bind do |value|
value > 1
? Right(value + 3)
: Left("value was less than 1")
end.bind do |value|
value % 2 == 0
? Right(value * 2)
: Left("value was not even")
end
end
l l 3 # i h 12
LOOKS FAMILIAR?
TRY MONAD
res = Try() { 10 / 2 }
res.value if res.success?
# => 5
res = Try() { 10 / 0 }
res.exception if res.failure?
# => #<ZeroDivisionError: divided by 0>
Try(NoMethodError, NotImplementedError) { 10 / 0 }
# => raised ZeroDivisionError: divided by 0 exception
AND OTHERS
List
Continuation
?
MONADS IN RUBY: EDITOR'S PICK
Maybe, Either monads. Looks like it's not supported anymore.
Option (actually, it's Maybe), Either, Result (similar to Either). Almost no contributions
are made for a long time.
Option (aka Maybe), Many (aka List), Eventually (aka Continuation). Is a demo for the
conference talk, but very clean and usable yet without any observable activity.
Maybe, Either, Try, Future, functional composition operators. Good quality code but is
abandoned in favor of its successor, dry-monads.
Maybe, Either, Try, List. Used by dry-rb ecosystem, most notable example is dry-
transactions. Fairly good and regular support. Has its community and used in real
projects.
monadic
deterministic
monads
kleisli
dry-monads
MONADS IN RUBY: HONORABLE
MENTIONS
One of the first gems in the field, was mentioned in a famous talk Railway-Oriented
programming
Remember, you can always write your own
solid_use_case
THANK YOU!
Questions?
1 of 35

Recommended

Bouncingballs sh by
Bouncingballs shBouncingballs sh
Bouncingballs shBen Pope
120 views8 slides
Area de un triangulo by
Area de un trianguloArea de un triangulo
Area de un trianguloIvan Ramirez Iglesias
646 views3 slides
Gambas by
Gambas Gambas
Gambas Gləndîz Fläkiitä
246 views13 slides
Unix programming ver_realfinal by
Unix programming ver_realfinalUnix programming ver_realfinal
Unix programming ver_realfinalHeeRa Kim
43 views33 slides
Beware sharp tools by
Beware sharp toolsBeware sharp tools
Beware sharp toolsAgileOnTheBeach
1.2K views57 slides
ejemplos gambas by
ejemplos gambasejemplos gambas
ejemplos gambaseduann
864 views34 slides

More Related Content

What's hot

March 2012-Marketing Roundtable- Dee Davey by
March 2012-Marketing Roundtable- Dee DaveyMarch 2012-Marketing Roundtable- Dee Davey
March 2012-Marketing Roundtable- Dee DaveyAnnArborSPARK
176 views2 slides
Pasos de proyecto1 by
Pasos de proyecto1Pasos de proyecto1
Pasos de proyecto1Ayhli123
616 views5 slides
Calculadora by
CalculadoraCalculadora
Calculadoraguestfb359f
147 views8 slides
Ejemplo En Gamabas by
Ejemplo En GamabasEjemplo En Gamabas
Ejemplo En Gamabaseduann
757 views34 slides
Ruby Topic Maps Tutorial (2007-10-10) by
Ruby Topic Maps Tutorial (2007-10-10)Ruby Topic Maps Tutorial (2007-10-10)
Ruby Topic Maps Tutorial (2007-10-10)Benjamin Bock
587 views42 slides
PHP Mailer Remote Code Execution by
PHP Mailer Remote Code ExecutionPHP Mailer Remote Code Execution
PHP Mailer Remote Code ExecutionNeelu Tripathy
841 views12 slides

What's hot(17)

March 2012-Marketing Roundtable- Dee Davey by AnnArborSPARK
March 2012-Marketing Roundtable- Dee DaveyMarch 2012-Marketing Roundtable- Dee Davey
March 2012-Marketing Roundtable- Dee Davey
AnnArborSPARK176 views
Pasos de proyecto1 by Ayhli123
Pasos de proyecto1Pasos de proyecto1
Pasos de proyecto1
Ayhli123616 views
Ejemplo En Gamabas by eduann
Ejemplo En GamabasEjemplo En Gamabas
Ejemplo En Gamabas
eduann757 views
Ruby Topic Maps Tutorial (2007-10-10) by Benjamin Bock
Ruby Topic Maps Tutorial (2007-10-10)Ruby Topic Maps Tutorial (2007-10-10)
Ruby Topic Maps Tutorial (2007-10-10)
Benjamin Bock587 views
PHP Mailer Remote Code Execution by Neelu Tripathy
PHP Mailer Remote Code ExecutionPHP Mailer Remote Code Execution
PHP Mailer Remote Code Execution
Neelu Tripathy841 views
Symfony 1.3 + Doctrine 1.2 by Jonathan Wage
Symfony 1.3 + Doctrine 1.2Symfony 1.3 + Doctrine 1.2
Symfony 1.3 + Doctrine 1.2
Jonathan Wage7.6K views
Fugly JavaScript by Tim Huegdon
Fugly JavaScriptFugly JavaScript
Fugly JavaScript
Tim Huegdon404 views
Programas Gambas by guestdd103d
Programas GambasProgramas Gambas
Programas Gambas
guestdd103d510 views
Programas Gambas by RZYMJ
Programas GambasProgramas Gambas
Programas Gambas
RZYMJ536 views
Auction model for resource scheduling in Cloud Foundry Diego by Amit Gupta
Auction model for resource scheduling in Cloud Foundry DiegoAuction model for resource scheduling in Cloud Foundry Diego
Auction model for resource scheduling in Cloud Foundry Diego
Amit Gupta1K views

Similar to Monads in Ruby - Victor Zagorodny

A Gentle Introduction to Functional Paradigms in Ruby by
A Gentle Introduction to Functional Paradigms in RubyA Gentle Introduction to Functional Paradigms in Ruby
A Gentle Introduction to Functional Paradigms in Rubycallmewuest
410 views34 slides
Reasonable Code With Fsharp by
Reasonable Code With FsharpReasonable Code With Fsharp
Reasonable Code With FsharpMichael Falanga
983 views29 slides
The Revenge of method_missing() by
The Revenge of method_missing()The Revenge of method_missing()
The Revenge of method_missing()paoloperrotta
2K views49 slides
F# intro by
F# introF# intro
F# introAlexey Raga
747 views22 slides
Ruby Intro {spection} by
Ruby Intro {spection}Ruby Intro {spection}
Ruby Intro {spection}Christian KAKESA
1.6K views46 slides
Lecture on Rubinius for Compiler Construction at University of Twente by
Lecture on Rubinius for Compiler Construction at University of TwenteLecture on Rubinius for Compiler Construction at University of Twente
Lecture on Rubinius for Compiler Construction at University of TwenteDirkjan Bussink
2K views121 slides

Similar to Monads in Ruby - Victor Zagorodny(20)

A Gentle Introduction to Functional Paradigms in Ruby by callmewuest
A Gentle Introduction to Functional Paradigms in RubyA Gentle Introduction to Functional Paradigms in Ruby
A Gentle Introduction to Functional Paradigms in Ruby
callmewuest410 views
The Revenge of method_missing() by paoloperrotta
The Revenge of method_missing()The Revenge of method_missing()
The Revenge of method_missing()
paoloperrotta2K views
Lecture on Rubinius for Compiler Construction at University of Twente by Dirkjan Bussink
Lecture on Rubinius for Compiler Construction at University of TwenteLecture on Rubinius for Compiler Construction at University of Twente
Lecture on Rubinius for Compiler Construction at University of Twente
Dirkjan Bussink2K views
Introduction to Kotlin.pptx by AzharFauzan9
Introduction to Kotlin.pptxIntroduction to Kotlin.pptx
Introduction to Kotlin.pptx
AzharFauzan94 views
Monads in python by eldariof
Monads in pythonMonads in python
Monads in python
eldariof7.8K views
Desarrollando aplicaciones web en minutos by Edgar J. Suárez
Desarrollando aplicaciones web en minutosDesarrollando aplicaciones web en minutos
Desarrollando aplicaciones web en minutos
Edgar J. Suárez756 views
MP in Clojure by Kent Ohashi
MP in ClojureMP in Clojure
MP in Clojure
Kent Ohashi4.1K views
Functional techniques in Ruby by erockendude
Functional techniques in RubyFunctional techniques in Ruby
Functional techniques in Ruby
erockendude278 views
Functional techniques in Ruby by erockendude
Functional techniques in RubyFunctional techniques in Ruby
Functional techniques in Ruby
erockendude375 views
Something about Golang by Anton Arhipov
Something about GolangSomething about Golang
Something about Golang
Anton Arhipov1.5K views
FParsec Hands On - F#unctional Londoners 2014 by Phillip Trelford
FParsec Hands On -  F#unctional Londoners 2014FParsec Hands On -  F#unctional Londoners 2014
FParsec Hands On - F#unctional Londoners 2014
Phillip Trelford11.8K views

More from Ruby Meditation

Is this Legacy or Revenant Code? - Sergey Sergyenko | Ruby Meditation 30 by
Is this Legacy or Revenant Code? - Sergey Sergyenko  | Ruby Meditation 30Is this Legacy or Revenant Code? - Sergey Sergyenko  | Ruby Meditation 30
Is this Legacy or Revenant Code? - Sergey Sergyenko | Ruby Meditation 30Ruby Meditation
207 views22 slides
Life with GraphQL API: good practices and unresolved issues - Roman Dubrovsky... by
Life with GraphQL API: good practices and unresolved issues - Roman Dubrovsky...Life with GraphQL API: good practices and unresolved issues - Roman Dubrovsky...
Life with GraphQL API: good practices and unresolved issues - Roman Dubrovsky...Ruby Meditation
462 views141 slides
Where is your license, dude? - Viacheslav Miroshnychenko | Ruby Meditation 29 by
Where is your license, dude? - Viacheslav Miroshnychenko | Ruby Meditation 29Where is your license, dude? - Viacheslav Miroshnychenko | Ruby Meditation 29
Where is your license, dude? - Viacheslav Miroshnychenko | Ruby Meditation 29Ruby Meditation
210 views49 slides
Dry-validation update. Dry-validation vs Dry-schema 1.0 - Aleksandra Stolyar ... by
Dry-validation update. Dry-validation vs Dry-schema 1.0 - Aleksandra Stolyar ...Dry-validation update. Dry-validation vs Dry-schema 1.0 - Aleksandra Stolyar ...
Dry-validation update. Dry-validation vs Dry-schema 1.0 - Aleksandra Stolyar ...Ruby Meditation
1.6K views59 slides
How to cook Rabbit on Production - Bohdan Parshentsev | Ruby Meditation 28 by
How to cook Rabbit on Production - Bohdan Parshentsev | Ruby Meditation 28 How to cook Rabbit on Production - Bohdan Parshentsev | Ruby Meditation 28
How to cook Rabbit on Production - Bohdan Parshentsev | Ruby Meditation 28 Ruby Meditation
366 views23 slides
How to cook Rabbit on Production - Serhiy Nazarov | Ruby Meditation 28 by
How to cook Rabbit on Production - Serhiy Nazarov | Ruby Meditation 28How to cook Rabbit on Production - Serhiy Nazarov | Ruby Meditation 28
How to cook Rabbit on Production - Serhiy Nazarov | Ruby Meditation 28Ruby Meditation
459 views20 slides

More from Ruby Meditation(20)

Is this Legacy or Revenant Code? - Sergey Sergyenko | Ruby Meditation 30 by Ruby Meditation
Is this Legacy or Revenant Code? - Sergey Sergyenko  | Ruby Meditation 30Is this Legacy or Revenant Code? - Sergey Sergyenko  | Ruby Meditation 30
Is this Legacy or Revenant Code? - Sergey Sergyenko | Ruby Meditation 30
Ruby Meditation207 views
Life with GraphQL API: good practices and unresolved issues - Roman Dubrovsky... by Ruby Meditation
Life with GraphQL API: good practices and unresolved issues - Roman Dubrovsky...Life with GraphQL API: good practices and unresolved issues - Roman Dubrovsky...
Life with GraphQL API: good practices and unresolved issues - Roman Dubrovsky...
Ruby Meditation462 views
Where is your license, dude? - Viacheslav Miroshnychenko | Ruby Meditation 29 by Ruby Meditation
Where is your license, dude? - Viacheslav Miroshnychenko | Ruby Meditation 29Where is your license, dude? - Viacheslav Miroshnychenko | Ruby Meditation 29
Where is your license, dude? - Viacheslav Miroshnychenko | Ruby Meditation 29
Ruby Meditation210 views
Dry-validation update. Dry-validation vs Dry-schema 1.0 - Aleksandra Stolyar ... by Ruby Meditation
Dry-validation update. Dry-validation vs Dry-schema 1.0 - Aleksandra Stolyar ...Dry-validation update. Dry-validation vs Dry-schema 1.0 - Aleksandra Stolyar ...
Dry-validation update. Dry-validation vs Dry-schema 1.0 - Aleksandra Stolyar ...
Ruby Meditation1.6K views
How to cook Rabbit on Production - Bohdan Parshentsev | Ruby Meditation 28 by Ruby Meditation
How to cook Rabbit on Production - Bohdan Parshentsev | Ruby Meditation 28 How to cook Rabbit on Production - Bohdan Parshentsev | Ruby Meditation 28
How to cook Rabbit on Production - Bohdan Parshentsev | Ruby Meditation 28
Ruby Meditation366 views
How to cook Rabbit on Production - Serhiy Nazarov | Ruby Meditation 28 by Ruby Meditation
How to cook Rabbit on Production - Serhiy Nazarov | Ruby Meditation 28How to cook Rabbit on Production - Serhiy Nazarov | Ruby Meditation 28
How to cook Rabbit on Production - Serhiy Nazarov | Ruby Meditation 28
Ruby Meditation459 views
Reinventing the wheel - why do it and how to feel good about it - Julik Tarkh... by Ruby Meditation
Reinventing the wheel - why do it and how to feel good about it - Julik Tarkh...Reinventing the wheel - why do it and how to feel good about it - Julik Tarkh...
Reinventing the wheel - why do it and how to feel good about it - Julik Tarkh...
Ruby Meditation462 views
Performance Optimization 101 for Ruby developers - Nihad Abbasov (ENG) | Ruby... by Ruby Meditation
Performance Optimization 101 for Ruby developers - Nihad Abbasov (ENG) | Ruby...Performance Optimization 101 for Ruby developers - Nihad Abbasov (ENG) | Ruby...
Performance Optimization 101 for Ruby developers - Nihad Abbasov (ENG) | Ruby...
Ruby Meditation475 views
Use cases for Serverless Technologies - Ruslan Tolstov (RUS) | Ruby Meditatio... by Ruby Meditation
Use cases for Serverless Technologies - Ruslan Tolstov (RUS) | Ruby Meditatio...Use cases for Serverless Technologies - Ruslan Tolstov (RUS) | Ruby Meditatio...
Use cases for Serverless Technologies - Ruslan Tolstov (RUS) | Ruby Meditatio...
Ruby Meditation320 views
The Trailblazer Ride from the If Jungle into a Civilised Railway Station - Or... by Ruby Meditation
The Trailblazer Ride from the If Jungle into a Civilised Railway Station - Or...The Trailblazer Ride from the If Jungle into a Civilised Railway Station - Or...
The Trailblazer Ride from the If Jungle into a Civilised Railway Station - Or...
Ruby Meditation285 views
What/How to do with GraphQL? - Valentyn Ostakh (ENG) | Ruby Meditation 27 by Ruby Meditation
What/How to do with GraphQL? - Valentyn Ostakh (ENG) | Ruby Meditation 27What/How to do with GraphQL? - Valentyn Ostakh (ENG) | Ruby Meditation 27
What/How to do with GraphQL? - Valentyn Ostakh (ENG) | Ruby Meditation 27
Ruby Meditation1.1K views
New features in Rails 6 - Nihad Abbasov (RUS) | Ruby Meditation 26 by Ruby Meditation
New features in Rails 6 -  Nihad Abbasov (RUS) | Ruby Meditation 26New features in Rails 6 -  Nihad Abbasov (RUS) | Ruby Meditation 26
New features in Rails 6 - Nihad Abbasov (RUS) | Ruby Meditation 26
Ruby Meditation577 views
Security Scanning Overview - Tetiana Chupryna (RUS) | Ruby Meditation 26 by Ruby Meditation
Security Scanning Overview - Tetiana Chupryna (RUS) | Ruby Meditation 26Security Scanning Overview - Tetiana Chupryna (RUS) | Ruby Meditation 26
Security Scanning Overview - Tetiana Chupryna (RUS) | Ruby Meditation 26
Ruby Meditation299 views
Teach your application eloquence. Logs, metrics, traces - Dmytro Shapovalov (... by Ruby Meditation
Teach your application eloquence. Logs, metrics, traces - Dmytro Shapovalov (...Teach your application eloquence. Logs, metrics, traces - Dmytro Shapovalov (...
Teach your application eloquence. Logs, metrics, traces - Dmytro Shapovalov (...
Ruby Meditation455 views
Best practices. Exploring - Ike Kurghinyan (RUS) | Ruby Meditation 26 by Ruby Meditation
Best practices. Exploring - Ike Kurghinyan (RUS) | Ruby Meditation 26Best practices. Exploring - Ike Kurghinyan (RUS) | Ruby Meditation 26
Best practices. Exploring - Ike Kurghinyan (RUS) | Ruby Meditation 26
Ruby Meditation204 views
Road to A/B testing - Alexey Vasiliev (ENG) | Ruby Meditation 25 by Ruby Meditation
Road to A/B testing - Alexey Vasiliev (ENG) | Ruby Meditation 25Road to A/B testing - Alexey Vasiliev (ENG) | Ruby Meditation 25
Road to A/B testing - Alexey Vasiliev (ENG) | Ruby Meditation 25
Ruby Meditation577 views
Concurrency in production. Real life example - Dmytro Herasymuk | Ruby Medita... by Ruby Meditation
Concurrency in production. Real life example - Dmytro Herasymuk | Ruby Medita...Concurrency in production. Real life example - Dmytro Herasymuk | Ruby Medita...
Concurrency in production. Real life example - Dmytro Herasymuk | Ruby Medita...
Ruby Meditation511 views
Data encryption for Ruby web applications - Dmytro Shapovalov (RUS) | Ruby Me... by Ruby Meditation
Data encryption for Ruby web applications - Dmytro Shapovalov (RUS) | Ruby Me...Data encryption for Ruby web applications - Dmytro Shapovalov (RUS) | Ruby Me...
Data encryption for Ruby web applications - Dmytro Shapovalov (RUS) | Ruby Me...
Ruby Meditation299 views
Rails App performance at the limit - Bogdan Gusiev by Ruby Meditation
Rails App performance at the limit - Bogdan GusievRails App performance at the limit - Bogdan Gusiev
Rails App performance at the limit - Bogdan Gusiev
Ruby Meditation418 views
GDPR. Next Y2K in 2018? - Anton Tkachov | Ruby Meditation #23 by Ruby Meditation
GDPR. Next Y2K in 2018? - Anton Tkachov | Ruby Meditation #23GDPR. Next Y2K in 2018? - Anton Tkachov | Ruby Meditation #23
GDPR. Next Y2K in 2018? - Anton Tkachov | Ruby Meditation #23
Ruby Meditation179 views

Recently uploaded

NTGapps NTG LowCode Platform by
NTGapps NTG LowCode Platform NTGapps NTG LowCode Platform
NTGapps NTG LowCode Platform Mustafa Kuğu
437 views30 slides
How to Re-use Old Hardware with CloudStack. Saving Money and the Environment ... by
How to Re-use Old Hardware with CloudStack. Saving Money and the Environment ...How to Re-use Old Hardware with CloudStack. Saving Money and the Environment ...
How to Re-use Old Hardware with CloudStack. Saving Money and the Environment ...ShapeBlue
171 views28 slides
State of the Union - Rohit Yadav - Apache CloudStack by
State of the Union - Rohit Yadav - Apache CloudStackState of the Union - Rohit Yadav - Apache CloudStack
State of the Union - Rohit Yadav - Apache CloudStackShapeBlue
303 views53 slides
"Package management in monorepos", Zoltan Kochan by
"Package management in monorepos", Zoltan Kochan"Package management in monorepos", Zoltan Kochan
"Package management in monorepos", Zoltan KochanFwdays
34 views18 slides
Live Demo Showcase: Unveiling Dell PowerFlex’s IaaS Capabilities with Apache ... by
Live Demo Showcase: Unveiling Dell PowerFlex’s IaaS Capabilities with Apache ...Live Demo Showcase: Unveiling Dell PowerFlex’s IaaS Capabilities with Apache ...
Live Demo Showcase: Unveiling Dell PowerFlex’s IaaS Capabilities with Apache ...ShapeBlue
129 views10 slides
VNF Integration and Support in CloudStack - Wei Zhou - ShapeBlue by
VNF Integration and Support in CloudStack - Wei Zhou - ShapeBlueVNF Integration and Support in CloudStack - Wei Zhou - ShapeBlue
VNF Integration and Support in CloudStack - Wei Zhou - ShapeBlueShapeBlue
207 views54 slides

Recently uploaded(20)

NTGapps NTG LowCode Platform by Mustafa Kuğu
NTGapps NTG LowCode Platform NTGapps NTG LowCode Platform
NTGapps NTG LowCode Platform
Mustafa Kuğu437 views
How to Re-use Old Hardware with CloudStack. Saving Money and the Environment ... by ShapeBlue
How to Re-use Old Hardware with CloudStack. Saving Money and the Environment ...How to Re-use Old Hardware with CloudStack. Saving Money and the Environment ...
How to Re-use Old Hardware with CloudStack. Saving Money and the Environment ...
ShapeBlue171 views
State of the Union - Rohit Yadav - Apache CloudStack by ShapeBlue
State of the Union - Rohit Yadav - Apache CloudStackState of the Union - Rohit Yadav - Apache CloudStack
State of the Union - Rohit Yadav - Apache CloudStack
ShapeBlue303 views
"Package management in monorepos", Zoltan Kochan by Fwdays
"Package management in monorepos", Zoltan Kochan"Package management in monorepos", Zoltan Kochan
"Package management in monorepos", Zoltan Kochan
Fwdays34 views
Live Demo Showcase: Unveiling Dell PowerFlex’s IaaS Capabilities with Apache ... by ShapeBlue
Live Demo Showcase: Unveiling Dell PowerFlex’s IaaS Capabilities with Apache ...Live Demo Showcase: Unveiling Dell PowerFlex’s IaaS Capabilities with Apache ...
Live Demo Showcase: Unveiling Dell PowerFlex’s IaaS Capabilities with Apache ...
ShapeBlue129 views
VNF Integration and Support in CloudStack - Wei Zhou - ShapeBlue by ShapeBlue
VNF Integration and Support in CloudStack - Wei Zhou - ShapeBlueVNF Integration and Support in CloudStack - Wei Zhou - ShapeBlue
VNF Integration and Support in CloudStack - Wei Zhou - ShapeBlue
ShapeBlue207 views
Initiating and Advancing Your Strategic GIS Governance Strategy by Safe Software
Initiating and Advancing Your Strategic GIS Governance StrategyInitiating and Advancing Your Strategic GIS Governance Strategy
Initiating and Advancing Your Strategic GIS Governance Strategy
Safe Software184 views
KVM Security Groups Under the Hood - Wido den Hollander - Your.Online by ShapeBlue
KVM Security Groups Under the Hood - Wido den Hollander - Your.OnlineKVM Security Groups Under the Hood - Wido den Hollander - Your.Online
KVM Security Groups Under the Hood - Wido den Hollander - Your.Online
ShapeBlue225 views
"Node.js Development in 2024: trends and tools", Nikita Galkin by Fwdays
"Node.js Development in 2024: trends and tools", Nikita Galkin "Node.js Development in 2024: trends and tools", Nikita Galkin
"Node.js Development in 2024: trends and tools", Nikita Galkin
Fwdays33 views
Business Analyst Series 2023 - Week 4 Session 7 by DianaGray10
Business Analyst Series 2023 -  Week 4 Session 7Business Analyst Series 2023 -  Week 4 Session 7
Business Analyst Series 2023 - Week 4 Session 7
DianaGray10146 views
Digital Personal Data Protection (DPDP) Practical Approach For CISOs by Priyanka Aash
Digital Personal Data Protection (DPDP) Practical Approach For CISOsDigital Personal Data Protection (DPDP) Practical Approach For CISOs
Digital Personal Data Protection (DPDP) Practical Approach For CISOs
Priyanka Aash162 views
Elevating Privacy and Security in CloudStack - Boris Stoyanov - ShapeBlue by ShapeBlue
Elevating Privacy and Security in CloudStack - Boris Stoyanov - ShapeBlueElevating Privacy and Security in CloudStack - Boris Stoyanov - ShapeBlue
Elevating Privacy and Security in CloudStack - Boris Stoyanov - ShapeBlue
ShapeBlue224 views
Hypervisor Agnostic DRS in CloudStack - Brief overview & demo - Vishesh Jinda... by ShapeBlue
Hypervisor Agnostic DRS in CloudStack - Brief overview & demo - Vishesh Jinda...Hypervisor Agnostic DRS in CloudStack - Brief overview & demo - Vishesh Jinda...
Hypervisor Agnostic DRS in CloudStack - Brief overview & demo - Vishesh Jinda...
ShapeBlue164 views
The Role of Patterns in the Era of Large Language Models by Yunyao Li
The Role of Patterns in the Era of Large Language ModelsThe Role of Patterns in the Era of Large Language Models
The Role of Patterns in the Era of Large Language Models
Yunyao Li91 views
Enabling DPU Hardware Accelerators in XCP-ng Cloud Platform Environment - And... by ShapeBlue
Enabling DPU Hardware Accelerators in XCP-ng Cloud Platform Environment - And...Enabling DPU Hardware Accelerators in XCP-ng Cloud Platform Environment - And...
Enabling DPU Hardware Accelerators in XCP-ng Cloud Platform Environment - And...
ShapeBlue108 views
Future of AR - Facebook Presentation by Rob McCarty
Future of AR - Facebook PresentationFuture of AR - Facebook Presentation
Future of AR - Facebook Presentation
Rob McCarty65 views

Monads in Ruby - Victor Zagorodny

  • 1. MONADS IN RUBY BY VICTOR ZAGORODNY Email: post.vittorius@gmail.com Twitter: https://twitter.com/vittoriuz Github: https://github.com/vittorius
  • 5. A monad is a monoid in the category of endofunctors, what's the problem? — James Iry
  • 8. LAZY EVALUATION EXAMPLE #1 (PSEUDOCODE): EXAMPLE #2: let numbers = [1, ...] fun is_prime x = all (map (y -> x mod y <> 0) [2..x-1]) let primes = filter is_prime numbers let tenth_prime = first (take primes 10) print tenth_prime if user.signed_in? && user.current_order&.pending? # ...
  • 9. WELCOME TO THE FUTURE f = Future.new do # executed asynchronously end f.complete? # non-blocking f.on_complete do |value| # called upon completion; preferred approach end f.value # blocks until complete; less preferred approach
  • 10. AN UGLY EXAMPLE users = UsersService.all archived_users = ArchivedUsersService.for_last_month (users + archived_users).select(&:active?).size
  • 11. FUNCTIONALLY BEAUTIFUL EXAMPLE count( only_active( concat( Future.new { UsersService.all }, Future.new { ArchivedUsersService.for_last_month } ) ) )
  • 12. FUNCTIONALLY BEAUTIFUL EXAMPLE count_f( only_active_f( concat_f( Future.new { UsersService.all }, Future.new { ArchivedUsersService.for_last_month } ) ) )
  • 13. INGREDIENTS: UNIT (aka "bind", "return") f = Future.new(x) # or f = Future.new f.complete_with(x) f.value # doesn't block f.complete? # == true class Future # unit : Value -> Future<Value> def self.unit(value) Future.new(value) end end
  • 14. INGREDIENTS: FMAP # count_f : Future<Enumerable> -> Future<Integer> def count_f(future) future.fmap( # f: Enumerable -> Integer ->(enumerable) { enumerable.count } ) end class Future # ... # fmap: Func<Value, Value> -> Future<Value> def fmap(func) f_new = Future.new on_complete do |value| f_new.complete_with(func.call(value)) end f_new end end
  • 15. INGREDIENTS: FMAP # only_active_f : Future<Enumerable> -> Future<Enumerable> def only_active_f(future) future.fmap( # f: Enumerable -> Enumerable ->(enumerable) { enumerable.select(&:active?) } ) end
  • 17. CHAINING FUTURES oops... f = Future.new { UsersService.all }.fmap( # f: Enumerable -> Future<Profile> ->(users) { Future.new { ProfileService.profile_for(users.first) } } ) f.value # let's get the profile of a first user... class Future def fmap(func) f_new = Future.new on_complete do |value| f_new.complete_with(func.call(value)) # it's a Future! end f_new end end
  • 18. INGREDIENTS: FLATTEN (aka "join") class Future # ... protected # flatten: Future<Future<Value>> -> Future<Value> def flatten f_flat = Future.new on_complete do |f_internal| f_internal.on_complete do |value| f_flat.complete_with(value) end end f_flat end end
  • 19. INGREDIENTS: BIND (aka "flatMap") class Future # ... # bind: Func<Value, Future<Value>> -> Future<Value> def bind(func) fmap(func).flatten end end
  • 20. CHAINING FUTURES CORRECTLY f = Future.new { UsersService.all }.bind( # f: Enumerable -> Future<Profile> ->(users) { Future.new { ProfileService.profile_for(users.first) } } ) # fmap(func).flatten was called under the hood f.value # now it's the Profile
  • 21. TWO IMPORTANT THINGS 1. Future is a monad Just believe me 2. I won't tell you how we built the concat_f function But I can give some clues
  • 22. LIFTING count -> lift -> count_f def lift(func) ->(future) { future.fmap(func) } end concat -> lift2 -> concat_f # Func<Value, Value, Value> # -> Func<Future<Value>, <Future<Value>, <Future<Value>> def lift2(func) # aka "liftM2" # ... end
  • 23. MONAD: DEFINITION (AT LAST) It's a data type It's a container for some (immutable) value It has a unit operation defined which wraps a value in it It has a bind operation defined which allows building a chain of transformations over a monadic value All of these make monad a "programmable semicolon"
  • 24. EXAMPLE: MAYBE MONAD class Maybe attr_reader :value class Some < Maybe def initialize(value) @value = value end end class None < Maybe; end end
  • 25. EXAMPLE: MAYBE MONAD class Maybe # "unit" function def self.[](value) value.nil? ? None.new : Some.new(value) end def bind(func) is_a?(None) ? self : func.call(self.value) end alias_method :>=, :bind end
  • 26. EXAMPLE: MAYBE MONAD (USAGE) # add_m2: # Func<Maybe<Integer>, Maybe<Integer>> -> Maybe<Integer> def add_m2(m1, m2) m1.>=( # calling bind ->(x) { # in binding function; value of m1 unpacked to x # we need to return Maybe from here; m2 is Maybe # m2.>= will also return Maybe m2.>=( # calling bind ->(y) { # value of m2 unpacked to y Maybe[x + y] # x and y are Integers # add them and wrap the result into Maybe }
  • 27. EXAMPLE: MAYBE MONAD (USAGE) add_m2(Maybe[1], Maybe[2]) # => Maybe::Some#<value = 3> add_m2(Maybe[4], Maybe[5]).value # => 9 add_m2(Maybe[nil], Maybe[5]) # => Maybe::None; "bind" of Maybe[5] was not executed
  • 28. MAYBE MONAD maybe_user = Maybe(user).bind do |u| Maybe(u.address).bind do |a| Maybe(a.street) end end # If user with address exists => Some("Street Address") # If user or address is nil => None()
  • 29. EITHER MONAD def calculate(input) Right(input).bind do |value| value > 1 ? Right(value + 3) : Left("value was less than 1") end.bind do |value| value % 2 == 0 ? Right(value * 2) : Left("value was not even") end end l l 3 # i h 12
  • 31. TRY MONAD res = Try() { 10 / 2 } res.value if res.success? # => 5 res = Try() { 10 / 0 } res.exception if res.failure? # => #<ZeroDivisionError: divided by 0> Try(NoMethodError, NotImplementedError) { 10 / 0 } # => raised ZeroDivisionError: divided by 0 exception
  • 33. MONADS IN RUBY: EDITOR'S PICK Maybe, Either monads. Looks like it's not supported anymore. Option (actually, it's Maybe), Either, Result (similar to Either). Almost no contributions are made for a long time. Option (aka Maybe), Many (aka List), Eventually (aka Continuation). Is a demo for the conference talk, but very clean and usable yet without any observable activity. Maybe, Either, Try, Future, functional composition operators. Good quality code but is abandoned in favor of its successor, dry-monads. Maybe, Either, Try, List. Used by dry-rb ecosystem, most notable example is dry- transactions. Fairly good and regular support. Has its community and used in real projects. monadic deterministic monads kleisli dry-monads
  • 34. MONADS IN RUBY: HONORABLE MENTIONS One of the first gems in the field, was mentioned in a famous talk Railway-Oriented programming Remember, you can always write your own solid_use_case