blog.bouzuya.net

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 をモナドの構造に適合させたものです.

Continuation モナド

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