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

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 のあたりが、

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

一週間後

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

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

参考:
Published on Wed, 28 Oct 2009 14:25

Haskell do記法

test = do
    x <- [1, 2]
    y <- [1, 2]
    return [x, y]

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

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

Published on Tue, 19 Feb 2008 23:15

今日のHaskell

フィボナッチ数列。

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

[…]

Published on Sat, 26 Jan 2008 19:55

RSS