2015/05/06
世の中はゴールデンウィークですね!今日は最終日です!!
GWは自由な時間がいっぱいあるのでたくさん勉強ができますね!(イヤッホー!)
というわけで暇な時間を持て余してHaskell by Exampleというコンテンツを作りました。(はてブ、スター、プルリクください!)
知ってる人も多いと思いますが[要出典]、もともとGo by ExampleというGoをExampleを通して学んでいこうという素晴らしいサイトがあって、Haskell by Exampleはそれを出来るだけそのままHaskellに翻訳したものです。
これを作った狙いはいくつかあって
と、そんな感じです。
もともとGoを勉強してた時、A Tour of Goをひと通りやって次にひたすらGo by Exampleを写経していました。Go by Exampleは適度な大きさで多様なトピックのコードが散らばってるので写経するととてもいい勉強になります。座学ではなく動くコードを書いて学ぶようなコンセプトだったので写経が終わったはあとすぐにGoを使ってコードを書き始めることができました。
Haskellは研究でも使われている言語なので入門となるとどうしても理論中心になってしまう気がするのですが、自分は普通に仕事でも使いたいと思ってるのでそういう人のためにも読んですぐ書けるようになるような入門が必要だと思いました。そんなこんなで昔お世話になったGo by ExampleをHaskellで書きなおそうと思ったわけです。
最初はHaskellだってなんでも書けるんだぞー!と思って作ってたのですが当然言語には向き不向きがあるわけでGoの良いところもあらためて勉強になりました。やっぱり非同期強い!
まずはSelect文。これはあらためて別の記事でも書こうと思ってるのですが、GoのSelect文に相当する機能がHaskellにはなくて無理やり自作しました。ネットで検索するとSTMで実装する方法とかも出てきましたが結局ひたすらMVarをtryする方法で実装しました。時間があれば他の方法も試してみたいです。とにかくHaskellでは以下のように書けるようになりました。
select [ Case messages $ \msg -> putStrLn $ "received message " ++ msg
, Case signals $ \sig -> putStrLn $ "received signal " ++ show sig
, Default $ putStrLn "no activiry"
]
元のSelect文そっくりですね(๑´ڡ`๑)
次にatomicです。Haskellでは代わりにSTMを使ってみましたが、失敗でした/(o)\。atomic が low-level なのに対してSTMは high-level ですからそもそも引き合いに出すのもおかしいと思うのですが、Goの例では50スレッドでひたすら1を毎回足すみたいな処理をやっていてそれをSTMでやろうとしたものですからたちまちメモリが食いつぶされてしまいました。なので毎回スレッドを眠らせるなどして何とか動くようにしましたが実行効率はかなり悪いですね… 普通にwithMVarとかで書いたほうがいいのだろうかとか思いつつ結局直さないままになっています。誰か助けて/(o)\
あとChan。GoのChanはclose出来るんですね!カッコイイ!HaskellのChanは無限長のチャネルを作ったらあとはひたすら読み書きするだけで閉じることができません… 閉じれないと何が不便かというともうデータが来ないという時点がわからないのでgetChanContents
を使ってリストとして取り出しても無限長リストになってるし工夫しないと永遠に終わらない処理しか書けなくなってしまいます。なのでClosableChan
みたいなデータ構造を作って開閉出来るようにすればいいと思うのですがめんどくさくなって放置しました…
あとTime。いっぱい型あるし小回りがきかなくて苦労しました…
なんだか愚痴っぽくなってしまいましたが読んでて分かる通り自分の無知と怠惰の結果な気もするのでもう少しがんばって修正しようと思います(^_^;)
あと当然HaskellにできてGoにできないこともたくさんあって例えば正規表現は書きませんでしたが(書きました)HaskellにはParsecという強力なパーサコンビネータがあります。STMもちゃんと使えばとても便利なものですし、MonadもLensもGoに無いから書いてないだけで必ず学ぶべきトピックだと思います。なので今後Go by Exampleからはみ出てHaskell特有のコードを書いていくこともしていきたいですね。
最後に、見たらすぐわかると思うのですがHaskell by Exampleの方には説明文がありません。理由は単純で僕が英語できないからです/(o)\もしも反響が大きくてGithubのスターが1000とか超えたらその時は英会話教室とかに通って英語勉強して説明もつけようと思いますw
以上いろいろ課題はあるのですが、今後もしばらく運用していくつもりなのでHaskell by Exampleをよろしくお願いしますm(__)m
またちょっとした修正とか気になったとことか俺が実装しなおしてやったよとかありましたらIssue/PullRequestを遠慮無くお願いします!
lotz84/haskellbyexample
日本語でも大丈夫ですのでー!