たぶんRubyでは 〜 Maybeモナドに憧れて 〜

投稿者 nanki 2009-10-28 14:25:00 GMT

HaskellにはMaybeモナドというのがあって、エラー処理をかなり適当な感じに書けてとても便利そう。

一方、多くのプログラミング言語では、

request.mobile && request.mobile.docomo?

File.open('example.txt').read rescue nil # これはすこし横着

こういった記述を頻繁に使う必要があり、なんとかしたい。

そこで、

class Never
  instance_methods.each do |v|
    undef_method(v) unless %w(__id__ __send__).include?(v)
  end

  def method_missing(*args)
    self
  end

  def end
    nil
  end
end

class Maybe < Never
  def initialize(value)
    @value = value
  end

  def method_missing(*args, &block)
    Maybe.new @value.__send__(*args, &block)
  rescue Exception
    Never.new
  end

  def end
    @value
  end
end

class Object
  def maybe
    Maybe.new(block_given? ? yield : self)
  rescue Exception
    Never.new
  end
end

上のようなコードを実行すると、

request.mobile.maybe.docomo?.end # => true/false or nil

File.maybe.open("file_does_not_exist.txt").read.end # => nil

こういう風に書く事ができるようになって幸せ。 途中のどこかで失敗すると、単にnilが返る。

このように、包んだオブジェクトのフリをするオブジェクトを使う手法はRailsでは多用されていて、読んでみると割と楽しい。ProxyObjectとか呼ぶらしい。

class Maybe < Never のあたりが、

子「お父さん、運動会絶対見に来てね」
父「絶対行くぞ」

一週間後

子「お父さん、運動会絶対見に来てね」
父「たぶん…」

というような会話を想像してしまって、とても人間的。

参考:

Haskell do記法

投稿者 nanki 2008-02-19 23:15:00 GMT
test = do
    x <- [1, 2]
    y <- [1, 2]
    return [x, y]

test = [1, 2] >>= (\x -> [1, 2] >>= (\y -> return [x, y]))

do記法は下のやつのSyntax Sugar. これはないと困る。


今日のHaskell

投稿者 nanki 2008-01-26 19:55:00 GMT

フィボナッチ数列。

readを見つけるのに、どれだけの時間を費やしたことか。
まだ、>>=の意味も、結合の優先順位も正確にはわかってないのでおそるおそる。

import System

fib :: Int -> Int
fib 0 = 0
fib 1 = 1
fib n = (fib $ n - 1) + (fib $ n - 2)

main = getArgs >>= print . fib . read . head