PythonでHaskellのMaybeモナド(もどき)を実装してみる
Haskellを勉強してきて、ようやくモナドの雰囲気がわかってきたので、Maybeモナドのような計算をPythonでやってみる。
#!/usr/bin/env python # -*- coding: utf-8 -*- # instance Monad Maybe where # return = Just # fail = Nothing def Maybe(x): return Just(x) if x else Nothing() class Just: def __init__(self, x): self.value = x def __repr__(self): return "Just(%r)" % self.value # (Just x) >>= f = f x def bind(self, f): return f(self.value) # '>>=' の代わりに '>>' をbind演算子として定義してみる def __rshift__(self, other): return self.bind(other) class Nothing: def __repr__(self): return "Nothing()" # Nothing >>= f = Nothing def bind(self, f): return self def __rshift__(self, other): return self.bind(other) nested_dict = {'a': {'b': {'c': 42}}} # あるキーで辞書を引く関数を返す関数 def lookup(key): return lambda d: Maybe(d.get(key)) print Maybe(nested_dict).bind(lookup('a')).bind(lookup('b')).bind(lookup('c')) # => Just(42) print Maybe(nested_dict) >> lookup('a') >> lookup('b') >> lookup('c') # => Just(42) print Maybe(nested_dict).bind(lookup('a')).bind(lookup('X')).bind(lookup('c')) # => Nothing() print Maybe(nested_dict) >> lookup('a') >> lookup('X') >> lookup('c') # => Nothing()
returnがプリミティブ値をモナドに入れて、bindがモナドの中身に何らかの処理をして新たなモナドを作る、do記法はbindの繰り返しを見やすく書くための糖衣構文、というあたりまでは掴めてきた。