読者です 読者をやめる 読者になる 読者になる

テストステ論

高テス協会会長が, テストステロンに関する情報をお届けします.

finchのEndpointはApplicative

finchの調査をひたすら続けている. s3実装をする上で十分な機能があるかどうかを見極めるためだ.

finagle/finch - Gitter

s3を実装する上で唯一の障壁となっているのが, EndpointがMonadでなくApplicativeであることだ.

実は, 0.8まではMonadだったのだが, 0.9に上げる時にApplicativeに落としたという経緯がある.

Demonstration of lazy, greedy, non-monadic routers by travisbrown · Pull Request #360 · finagle/finch · GitHub

なぜEndpointがMonadじゃないといけないかというと, コンテキストを運べないからだ. それが現実に問題になっているのが, s3が, リクエストに対して発行されたRequest IDをException Handlerに含むという仕様だ.

私がGitterチャンネルで説明に使った擬似コードがこれ

endpoint1 { ID =>
   endpoint2 { a =>
   }.handle { use ID }
}

もしこれが出来ないとすると, 例外が実際に起こるところまでIDを運んでいき, 例外で包んでhandleの中に運んであげる必要が出てくる. これは明らかに, ソフトウェアとしての作りがおかしい. 従って, このような瑣末な情報をメインパスでぐだぐだと運ばないために, EndpointはMonadicであるべきだというのだ.

この主張は, finchの開発者に理解された. しかし彼はApplicativeが好きらしい. 私はこれを, 彼がコンパイラのバックグラウンドを持っているからだと推測するが, 間違ってるかもしれない.

代わりに, もしEndpointにflatMapを実装するならばPRを受け付けると約束してくれた. 私はこれを昨晩少し試した. しかし, 難しい... まぁ, なんとか出来るような気はしないでもないのでハードな演習と思ってやってみる.

trait Endpoint[A] { self =>
  /**
   * Extracts some value of type `A` from the given `input`.
   */
  // There is a reason why it can't be renamed to `run` as per https://github.com/finagle/finch/issues/371.
  // More details are here: http://stackoverflow.com/questions/32064375/magnet-pattern-and-overloaded-methods
  def apply(input: Input): Option[(Input, () => Future[Output[A]])]

なぜおれはs3を実装したいだけなのに, 関数型プログラミングをしなければいけないのだろうか・・・.