技術memo

関数型ゴースト

任意型リストのsplit/join

ご無沙汰してます。忙しさにかまけて、あまり技術の勉強メモすら捗らない昨今です。

Twitterでお題が出されていたので、それとなくF# でやってみました。

任意型リストのsplit

ついでにjoinもしてみます

任意型リストのjoin

listを見たらfoldを考える、何もないところからlistを生み出したければunfoldを考えるのが、ある種「関数型っぽさ」か、とは思います。もちろん標準モジュールに定義されてる関数は使っていきましょう。自前の再帰関数(let rec ~)は、listやseq相手にはあまり考えません。 F# ならこういう場合はseq式を使うのがいいという意見も見られたのですが、それはまあどなたかがやってくれるでしょう。

一時データにx::xsで積み上げて行って最後に反転するパターンは、わかりやすいですが、無限リストに対応できないので、そこは注意ですね。実用上は「とりあえず」然程問題にはなりませんが。

あまり関係がないことですが、久々にF# / Visual Studioを使うと、Emacs対応キーバインドが無くてつらさがあります。ここは一旦妥協してVsVimに学習コストを割くべきでしょうか。

といったところで、今回はこの辺で。

2015-7-14 追記

この記事をGitterのFSUGJPに放り投げておいたら、id:htid46 さんが改良版を投げてくれたので紹介します。

任意型リストのsplit(その2 by id:htid46)

任意型リストのjoin(その2 by id:htid46)

foldBack関数は、他の言語等ではfold rightと呼ばれる、逆順での畳込みですね。使い分けに関しては次の記事が詳しいです。Haskellの遅延評価&遅延リストとF# の正格評価&正格リストでは、若干違う点もありますけど。

畳込関数fold:foldrとfoldlの違い (あるいはfold_right, fold_left) - 一歩前進

左foldと右foldの使い分けができるようになると、いい感じですね。私は右foldはまだどうも不慣れです。

join2の方は、fold時に工夫しておけば、後で1要素飛ばすという無駄な処理が不要になるということですね。迂闊でした。

何にしても、「記述の簡潔さ」もありますが、処理速度や専有メモリのオーダーまで見込んで判断できればカンペキだと思います。でも今回のところは、もう気にしないことにします。