What would be the maybe monad for crystal.
Here for other languages,
http://www.rosettacode.org/wiki/Monads/Maybe_monad
Unless I’m misunderstanding what the Maybe Monad is, Crystal uses Nil unions for this. For example, the return type of Array(T)#min? is T | Nil (which is the same as T?) because there’s no minimum if the Array is empty. So, in that case, T | Nil is the same as a hypothetical type Maybe(T).
Exactly. In Crystal map is Object#try. As an example, the code presented in the rosettacode for Ruby:
class Maybe
def initialize(value)
@value = value
end
def map
if @value.nil?
self
else
Maybe.new(yield @value)
end
end
end
Maybe.new(3).map { |n| 2*n }.map { |n| n+1 }
#=> #<Maybe @value=7>
Maybe.new(nil).map { |n| 2*n }.map { |n| n+1 }
#=> #<Maybe @value=nil>
Maybe.new(3).map { |n| nil }.map { |n| n+1 }
#=> #<Maybe @value=nil>
Becomes in Crystal:
3.try { |n| 2*n }.try { |n| n+1 }
#=> 7
nil.try { |n| 2*n }.try { |n| n+1 }
#=> nil
3.try { |n| nil }.try { |n| n+1 }
#=> nil
Look ma, no wrapper! ![]()
@Alain, since you brought the topic, do you want to post the example in rosettacode? (I’ll do it otherwise).
If you do, post the link and I’ll include it in the Rosetta Code list. ![]()
A real Maybe ensures that Just and None are always disjoint, so Maybe(T) = T | Nil doesn’t suffice as T is nilable. A real implementation might be:
record Just(T), value : T
record None
# alias Maybe(T) = Just(T) | None
module Enumerable(T)
def find2(& : T ->) : Just(T) | None
each do |elem|
return Just.new(elem) if yield elem
end
None.new
end
end
def show(x)
case x
in Just; p x.value
in None; puts "(none)"
end
end
show [nil, 1].find2 { true } # => nil
show [nil, 1].find2 { false } # => (none)
Actual monadic operations tend to manifest as noise rather than a benefit in a language like Crystal, which I imagine is why the standard library isn’t based on monads. There are probably some shards out there that provide Maybe and other true monads.
Fair enough, but if you stack up Maybes, in most cases you don’t care where the None comes from (otherwise, you’ll use a more informative monad).