Rubyでモナドの練習メモ

Haskellに登場するらしいモナドを少し勉強してみる。よくわからないが、試しにMaybeモナドRubyで書いてみた。どこか間違えていると思うが、コードは下記。

class Maybe
  def Maybe.wrap( value )
    Maybe.new(value)
  end

  attr_accessor :value
  def initialize(value)
    @value = value
  end

  def pass
    if @value.nil?
      Maybe.new(nil)
    else
      yield @value
    end
  end
end

def div6(x)
  if x == 0
    nil
  else
    6 / x
  end
end

def inc(x)
  x + 1
end

def normal_div6_inc(x)
  rv = div6(x)
  if rv
    inc(x)
  else
    nil
  end
end

def maybe_div6_inc(x)
  Maybe.wrap( div6(x) ).pass {|v|
    Maybe.wrap(inc(v))
  }.value
end

p maybe_div6_inc(2) # -> 4
p maybe_div6_inc(0) # -> nil

Maybeは実行が失敗し得る関数を合成する時に用いるらしい。上の例だと、div6は引数が0の場合、nilを返す。したがって、div6とinc合成する場合、if文による返り値のチェックが必要となる。この仕組みを抽象化してMaybeクラスに落とし込んでいる。

たしかに、関数合成を多用する関数言語では便利かも。

参考にしたページは下記。
http://moonbase.rydia.net/mental/writings/programming/monads-in-ruby/00introduction.html
http://howm.sourceforge.jp/cgi-bin/hiki/hiki.cgi?Monad