2016-12-30 purescript-transformers の ContT monad を調べた
purescript-node-http パッケージの Node.HTTP.Client モジュールを使おうとして、いろいろ調べることになった。
結論から言うと PureScript by Example をきちんと読めばだいたいのことは書いてある。
Node.HTTP.Client モジュールは Node.js の http パッケージを wrap したものだ。おおむね似たような API を備えている。これを使うことによって登場する要素には次のようなものがある。
- callback
- Node.js Stream
on('data', ...)の chunk の集約
これらのすべてをまだ解決しているわけではない。
今日はまず callback だ。 callback が大量に発生するといわゆるコールバック地獄 (callback hell) に陥る。これを避けるために調べていると ContT にたどりついた。これは「継続モナド (Continuation Monad) 」と呼ばれるものらしい。追記: 継続モナド Cont にできる継続モナド変換子の誤り。
callback という、ある処理に続く処理 (継続) を渡す形式は「継続渡し形式 (CPS : Continuation Passing Style) 」と呼ぶらしい。いくつかの参考を挙げておく『継続渡し形式(CPS)』・『なんでも継続』。
ContT はこの CPS をモナドの構造に適合させたものらしい。
Continutation モナドは CPS をモナドの構造に適合させたものです.
PureScript では Cont / ContT が purescript-transformers パッケージにある。Pursuit は次のとおりだ。
- Cont - Control.Monad.Cont - purescript-transformers - Pursuit
- ContT - Control.Monad.Cont.Trans - purescript-transformers - Pursuit
ぼくの感覚では JavaScript の Promise から例外処理を取っ払ったイメージで使っている。それぞれの処理から ContT を構築し、一連の処理を bind して、最後は runContT でひとつの callback に集約できる。 Promise の連鎖をつくるような感じ。これでひとつ問題が解決しそうだ。
しかし、これだと例外処理ができないので、同パッケージの ExceptT を組み合わせたほうが良さそうだ。さらに、それらをよしなに扱ってくれる purescript-aff パッケージの Aff を使うと良さそうな気はする。……が、そこまでは進められていない。
案外、それらをすっ飛ばして FFI : Foreign Function Interface でなんとかすると早い気もする。Node.js の http パッケージの client って JavaScript でさえ使いやすいと感じないわけだし……。ぼくのように JSON をポンと取れれば十分な層には不要な気もする。現に PureScript by Example の 12 章の例では、NPM から request パッケージを取ってきて、それを使っている。
今後の勉強のためにも、とりあえずは Node.HTTP.Client モジュールでがんばってみようと思っているのだけど……。明日は大晦日なので、ふりかえり記事になるだろう。