Skip to content

Instantly share code, notes, and snippets.

@fmnoise
Last active May 27, 2017 13:32
Show Gist options
  • Save fmnoise/536ee4a9ca4687fb0d324d3c1899097c to your computer and use it in GitHub Desktop.
Save fmnoise/536ee4a9ca4687fb0d324d3c1899097c to your computer and use it in GitHub Desktop.
Simple Ruby implementations of some monads (just for fun)
module Monads
class Box
def self.[](value)
self.new(value)
end
def initialize(value)
@value = value
end
def >>
self.class.new yield @value
end
def <=
block_given? ? yield(@value) : @value
end
end
class Maybe < Box
def >>
self.class.new(@value.nil? ? nil : block_given? ? yield(@value) : @value)
end
def <=
@value.nil? ? nil : block_given? ? yield(@value) : @value
end
end
class Try
def self.to
Right[yield]
rescue StandardError => e
Left[e]
end
class Right < Box
def >>
self.class[yield @value]
rescue StandardError => e
Left[e]
end
def <=
yield nil, @value
end
end
class Left < Box
def >>
self
end
def <=
yield @value, nil
end
end
end
end
###############################
# Box
#----------before--------------
def filtered_sales
filter_by_tags \
filter_by_category \
filter_by_client \
filter_by_seller \
sales_by_dates
end
#----------after--------------
def filtered_sales
Monads::Box[sales_by_dates].
>> {|v| filter_by_seller v}.
>> {|v| filter_by_client v}.
>> {|v| filter_by_category v}.
<= {|v| filter_by_tags v}
end
###############################
###############################
# Maybe
#----------before--------------
def email_service user_id
if user = User.find_by_id(user_id)
if email = user.email
if service = email.split('@').last
service.upcase
end
end
end
end
#----------after--------------
def email_service user_id
Monads::Maybe[user_id].
>> {|v| User.find_by_id(v)}.
>> (&:email).
>> {|v| v.split '@'}.
>> (&:last).
<= (&:upcase)
end
###############################
# Try aka Either
#----------before--------------
def get_service_port default_port
begin
file = File.open('config.json')
config = JSON.parse(file)
config['port'] || default_port
rescue StandardError => e
default_port
end
end
def get_service_port default_port
Monads::Try.to { File.open('config.json') }.
>> {|v| JSON.parse v }.
>> {|v| v['port'] || default_port }.
<= {|err,v| err ? default_port : v }
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment