Goとモナド
Goとerror monads - moriyoshiの日記
ちょっとそれをモナドって呼んだらHaskellerやってきますよ? (太宰メソッド)
just型の構造体にfuncって関数で(interface {}, error)の値を遅延して持たせているのは奇妙だ。
こういう風に、もっとわかりやすく書きたい。
package main import ( "log" "os" ) type right struct { val interface{} } type left struct { val error } type either interface { Fmap(func(interface{}) interface{}) either Bind(func(interface{}) (interface{}, error)) either Elim(func(error) interface{}) interface{} } func (m *right) Fmap(f func(interface{}) interface{}) either { return &right{f(m.val)} } func (m *left) Fmap(f func(interface{}) interface{}) either { return m } func (m *right) Bind(k func(interface{}) (interface{}, error)) either { v, err := k(m.val) if err != nil { return &left{err} } return &right{v} } func (m *left) Bind(k func(interface{}) (interface{}, error)) either { return m } func Pure(v interface{}) either { return &right{v} } func (m *right) Elim(f func(error) interface{}) interface{} { return m.val } func (m *left) Elim(f func(error) interface{}) interface{} { return f(m.val) } func main() { if err := Pure("hello.txt"). Bind(func(s interface{}) (interface{}, error) { return os.Open(s.(string)) } ). Fmap(func(f interface{}) interface{} { return f.(*os.File).Close() }). Elim(func(err error) interface{} { return err }); err != nil { log.Fatalln(err) } }
実行結果:
go$ go build either.go go$ ./either 2013/10/20 03:29:20 open hello.txt: no such file or directory go$ touch hello.txt go$ ./either go$ rm hello.txt go$ ./either 2013/10/20 03:29:35 open hello.txt: no such file or directory go$
ぶっちゃけGo言語ってこういう書き方に向いていない。せめてジェネリクスは欲しいよね。