tomstuart/monads
Simple Ruby implementations of some common monads.
{ "createdAt": "2014-08-02T13:52:07Z", "defaultBranch": "master", "description": "Simple Ruby implementations of some common monads.", "fullName": "tomstuart/monads", "homepage": "https://tomstu.art/refactoring-ruby-with-monads", "language": "Ruby", "name": "monads", "pushedAt": "2019-09-08T09:18:50Z", "stargazersCount": 616, "topics": [], "updatedAt": "2025-11-14T07:04:27Z", "url": "https://github.com/tomstuart/monads"}Monads
Section titled “Monads”This library provides simple Ruby implementations of some common monads.
The most important method of each implementation is #and_then (a.k.a. bind or >>=), which is used to connect together a sequence of operations involving the value(s) inside the monad. Each monad also has a .from_value class method (a.k.a. return or unit) for constructing an instance of that monad from an arbitrary value.
Optional
Section titled “Optional”(a.k.a. the maybe monad)
An Optional object contains a value that might be nil.
>> require 'monads/optional'=> true
>> include Monads=> Object
>> optional_string = Optional.new('hello world')=> #<struct Monads::Optional value="hello world">
>> optional_result = optional_string.and_then { |string| Optional.new(string.upcase) }=> #<struct Monads::Optional value="HELLO WORLD">
>> optional_result.value=> "HELLO WORLD"
>> optional_string = Optional.new(nil)=> #<struct Monads::Optional value=nil>
>> optional_result = optional_string.and_then { |string| Optional.new(string.upcase) }=> #<struct Monads::Optional value=nil>
>> optional_result.value=> nil(a.k.a. the list monad)
A Many object contains multiple values.
>> require 'monads/many'=> true
>> include Monads=> Object
>> many_strings = Many.new(['hello world', 'goodbye world'])=> #<struct Monads::Many values=["hello world", "goodbye world"]>
>> many_results = many_strings.and_then { |string| Many.new(string.split(/ /)) }=> #<struct Monads::Many values=["hello", "world", "goodbye", "world"]>
>> many_results.values=> ["hello", "world", "goodbye", "world"]Eventually
Section titled “Eventually”(a.k.a. the continuation monad)
An Eventually object contains a value that will eventually be available, perhaps as the result of an asynchronous process (e.g. a network request).
>> require 'monads/eventually'=> true
>> include Monads=> Object
>> eventually_string = Eventually.new do |success| Thread.new do sleep 5 success.call('hello world') end end=> #<struct Monads::Eventually block=#<Proc>>
>> eventually_result = eventually_string.and_then do |string| Eventually.new do |success| Thread.new do sleep 5 success.call(string.upcase) end end end=> #<struct Monads::Eventually block=#<Proc>>
>> eventually_result.run { |string| puts string }=> #<Thread run>HELLO WORLD