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
モジュールでがんばってみようと思っているのだけど……。明日は大晦日なので、ふりかえり記事になるだろう。