SlideShare uma empresa Scribd logo
1 de 35
Baixar para ler offline
MONADS IN RUBY
BY VICTOR ZAGORODNY
Email: post.vittorius@gmail.com
Twitter: https://twitter.com/vittoriuz
Github: https://github.com/vittorius
MONADS: WHAT IS IT?
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
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?

Mais conteúdo relacionado

Mais procurados

March 2012-Marketing Roundtable- Dee Davey
March 2012-Marketing Roundtable- Dee DaveyMarch 2012-Marketing Roundtable- Dee Davey
March 2012-Marketing Roundtable- Dee DaveyAnnArborSPARK
 
Pasos de proyecto1
Pasos de proyecto1Pasos de proyecto1
Pasos de proyecto1Ayhli123
 
Ejemplo En Gamabas
Ejemplo En GamabasEjemplo En Gamabas
Ejemplo En Gamabaseduann
 
Ruby Topic Maps Tutorial (2007-10-10)
Ruby Topic Maps Tutorial (2007-10-10)Ruby Topic Maps Tutorial (2007-10-10)
Ruby Topic Maps Tutorial (2007-10-10)Benjamin Bock
 
PHP Mailer Remote Code Execution
PHP Mailer Remote Code ExecutionPHP Mailer Remote Code Execution
PHP Mailer Remote Code ExecutionNeelu Tripathy
 
Symfony 1.3 + Doctrine 1.2
Symfony 1.3 + Doctrine 1.2Symfony 1.3 + Doctrine 1.2
Symfony 1.3 + Doctrine 1.2Jonathan Wage
 
Fugly JavaScript
Fugly JavaScriptFugly JavaScript
Fugly JavaScriptTim Huegdon
 
Programas Gambas
Programas GambasProgramas Gambas
Programas Gambasguestdd103d
 
Programas Gambas
Programas GambasProgramas Gambas
Programas GambasRZYMJ
 
Auction model for resource scheduling in Cloud Foundry Diego
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 DiegoAmit Gupta
 
Maze solving app listing
Maze solving app listingMaze solving app listing
Maze solving app listingChris Worledge
 

Mais procurados (17)

March 2012-Marketing Roundtable- Dee Davey
March 2012-Marketing Roundtable- Dee DaveyMarch 2012-Marketing Roundtable- Dee Davey
March 2012-Marketing Roundtable- Dee Davey
 
Pasos de proyecto1
Pasos de proyecto1Pasos de proyecto1
Pasos de proyecto1
 
Calculadora
CalculadoraCalculadora
Calculadora
 
Ejemplo En Gamabas
Ejemplo En GamabasEjemplo En Gamabas
Ejemplo En Gamabas
 
Ruby Topic Maps Tutorial (2007-10-10)
Ruby Topic Maps Tutorial (2007-10-10)Ruby Topic Maps Tutorial (2007-10-10)
Ruby Topic Maps Tutorial (2007-10-10)
 
PHP Mailer Remote Code Execution
PHP Mailer Remote Code ExecutionPHP Mailer Remote Code Execution
PHP Mailer Remote Code Execution
 
Gambas
GambasGambas
Gambas
 
Symfony 1.3 + Doctrine 1.2
Symfony 1.3 + Doctrine 1.2Symfony 1.3 + Doctrine 1.2
Symfony 1.3 + Doctrine 1.2
 
Fugly JavaScript
Fugly JavaScriptFugly JavaScript
Fugly JavaScript
 
Kidflier6.5
Kidflier6.5Kidflier6.5
Kidflier6.5
 
Yolygambas
YolygambasYolygambas
Yolygambas
 
2 Graph Theory
2 Graph Theory2 Graph Theory
2 Graph Theory
 
Programas Gambas
Programas GambasProgramas Gambas
Programas Gambas
 
Programas Gambas
Programas GambasProgramas Gambas
Programas Gambas
 
Manual De Gambas
Manual De GambasManual De Gambas
Manual De Gambas
 
Auction model for resource scheduling in Cloud Foundry Diego
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
 
Maze solving app listing
Maze solving app listingMaze solving app listing
Maze solving app listing
 

Semelhante a Monads in Ruby - Victor Zagorodny

A Gentle Introduction to Functional Paradigms in Ruby
A Gentle Introduction to Functional Paradigms in RubyA Gentle Introduction to Functional Paradigms in Ruby
A Gentle Introduction to Functional Paradigms in Rubycallmewuest
 
Reasonable Code With Fsharp
Reasonable Code With FsharpReasonable Code With Fsharp
Reasonable Code With FsharpMichael Falanga
 
The Revenge of method_missing()
The Revenge of method_missing()The Revenge of method_missing()
The Revenge of method_missing()paoloperrotta
 
Lecture on Rubinius for Compiler Construction at University of Twente
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
 
Introduction to Kotlin.pptx
Introduction to Kotlin.pptxIntroduction to Kotlin.pptx
Introduction to Kotlin.pptxAzharFauzan9
 
01 Introduction to Kotlin - Programming in Kotlin.pptx
01 Introduction to Kotlin - Programming in Kotlin.pptx01 Introduction to Kotlin - Programming in Kotlin.pptx
01 Introduction to Kotlin - Programming in Kotlin.pptxIvanZawPhyo
 
Monads in python
Monads in pythonMonads in python
Monads in pythoneldariof
 
Desarrollando aplicaciones web en minutos
Desarrollando aplicaciones web en minutosDesarrollando aplicaciones web en minutos
Desarrollando aplicaciones web en minutosEdgar Suarez
 
Functions, Types, Programs and Effects
Functions, Types, Programs and EffectsFunctions, Types, Programs and Effects
Functions, Types, Programs and EffectsRaymond Roestenburg
 
Functional techniques in Ruby
Functional techniques in RubyFunctional techniques in Ruby
Functional techniques in Rubyerockendude
 
Functional techniques in Ruby
Functional techniques in RubyFunctional techniques in Ruby
Functional techniques in Rubyerockendude
 
A simple study on computer algorithms by S. M. Risalat Hasan Chowdhury
A simple study on computer algorithms by S. M. Risalat Hasan ChowdhuryA simple study on computer algorithms by S. M. Risalat Hasan Chowdhury
A simple study on computer algorithms by S. M. Risalat Hasan ChowdhuryS. M. Risalat Hasan Chowdhury
 
Something about Golang
Something about GolangSomething about Golang
Something about GolangAnton Arhipov
 

Semelhante a Monads in Ruby - Victor Zagorodny (20)

A Gentle Introduction to Functional Paradigms in Ruby
A Gentle Introduction to Functional Paradigms in RubyA Gentle Introduction to Functional Paradigms in Ruby
A Gentle Introduction to Functional Paradigms in Ruby
 
Reasonable Code With Fsharp
Reasonable Code With FsharpReasonable Code With Fsharp
Reasonable Code With Fsharp
 
The Revenge of method_missing()
The Revenge of method_missing()The Revenge of method_missing()
The Revenge of method_missing()
 
F# intro
F# introF# intro
F# intro
 
Ruby Intro {spection}
Ruby Intro {spection}Ruby Intro {spection}
Ruby Intro {spection}
 
Lecture on Rubinius for Compiler Construction at University of Twente
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
 
Introduction to Kotlin.pptx
Introduction to Kotlin.pptxIntroduction to Kotlin.pptx
Introduction to Kotlin.pptx
 
01 Introduction to Kotlin - Programming in Kotlin.pptx
01 Introduction to Kotlin - Programming in Kotlin.pptx01 Introduction to Kotlin - Programming in Kotlin.pptx
01 Introduction to Kotlin - Programming in Kotlin.pptx
 
Ict project pdf
Ict project pdfIct project pdf
Ict project pdf
 
Monads in python
Monads in pythonMonads in python
Monads in python
 
Desarrollando aplicaciones web en minutos
Desarrollando aplicaciones web en minutosDesarrollando aplicaciones web en minutos
Desarrollando aplicaciones web en minutos
 
Steady with ruby
Steady with rubySteady with ruby
Steady with ruby
 
MP in Clojure
MP in ClojureMP in Clojure
MP in Clojure
 
An introduction to Ruby
An introduction to RubyAn introduction to Ruby
An introduction to Ruby
 
Functions, Types, Programs and Effects
Functions, Types, Programs and EffectsFunctions, Types, Programs and Effects
Functions, Types, Programs and Effects
 
Functional techniques in Ruby
Functional techniques in RubyFunctional techniques in Ruby
Functional techniques in Ruby
 
Functional techniques in Ruby
Functional techniques in RubyFunctional techniques in Ruby
Functional techniques in Ruby
 
A simple study on computer algorithms by S. M. Risalat Hasan Chowdhury
A simple study on computer algorithms by S. M. Risalat Hasan ChowdhuryA simple study on computer algorithms by S. M. Risalat Hasan Chowdhury
A simple study on computer algorithms by S. M. Risalat Hasan Chowdhury
 
Something about Golang
Something about GolangSomething about Golang
Something about Golang
 
Designing Ruby APIs
Designing Ruby APIsDesigning Ruby APIs
Designing Ruby APIs
 

Mais de Ruby Meditation

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

Mais de Ruby Meditation (20)

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

Último

My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024Stephanie Beckett
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):comworks
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machinePadma Pradeep
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr LapshynFwdays
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 
The Future of Software Development - Devin AI Innovative Approach.pdf
The Future of Software Development - Devin AI Innovative Approach.pdfThe Future of Software Development - Devin AI Innovative Approach.pdf
The Future of Software Development - Devin AI Innovative Approach.pdfSeasiaInfotech2
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024The Digital Insurer
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenHervé Boutemy
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsMemoori
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...Fwdays
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfAddepto
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clashcharlottematthew16
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024Lorenzo Miniero
 

Último (20)

My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machine
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 
The Future of Software Development - Devin AI Innovative Approach.pdf
The Future of Software Development - Devin AI Innovative Approach.pdfThe Future of Software Development - Devin AI Innovative Approach.pdf
The Future of Software Development - Devin AI Innovative Approach.pdf
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache Maven
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial Buildings
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
 
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptxE-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdf
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clash
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024
 

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
  • 2.
  • 4.
  • 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
  • 16.
  • 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