LoginSignup
7
1

More than 5 years have passed since last update.

Haskell っぽく JavaScript で関数合成したい

Last updated at Posted at 2017-12-12

Lodash-fp を使って JavaScript で関数合成してみます。
Lodash-fp は有名なユーティリティライブラリ Lodash の関数型プログラミングっぽくかけるモジュールの1つです。

前提知識

  • JavaScript の基本的な開発経験があること
  • Haskell は比較対象として登場しますが知らなくてもたぶん読めます

簡単な例題から考える

例題: 配列 [7,2,3,6] の各値に1を加えて偶数の値だけ取り出してすべて足す。

  1. 各要素に1を足す(map)
    [7,2,3,6] -> [8,3,4,7]
  2. 偶数の値だけ取り出す(filter)
    [8,3,4,7] -> [8,4]
  3. すべての要素を足す(sum)
    [8,4] -> 12

上記の問題設定自体には特に意味はありません。

Haskell

愚直にカッコを多用して Haskell で書いてみます。

xs = [7, 2, 3, 6]
sum (filter (\t -> t `mod` 2 == 0) (map (\x -> x + 1) xs))

Haskell with point-free style

Haskell っぽくポイントフリー(関数合成)スタイルで書いてみます。

xs = [7, 2, 3, 6]
f = sum . filter ((0 ==) . flip mod 2) . map (+ 1)
f xs

もっと短くも書けます。

f = sum . filter even . map (+1)

Lodash

次は Lodash を使って JavaScript で書いてみます。

const _ = require('lodash');
const xs = [7, 2, 3, 6];
_.sum(_.filter(_.map(xs, x => x + 1), t => t % 2 == 0));

Lodash with chain

JavaScript っぽく chain で書いてみます。

const _ = require('lodash');
const xs = [7, 2, 3, 6];
_.chain(xs).map(x => x + 1).filter(t => t % 2 == 0).sum().value();

chain はやはり最後に必要な value() が残念な感じがします。
Why using _.chain is a mistake.

Lodash-fp

Lodash-fp を使って JavaScript で書いてみます。

const fp = require('lodash/fp');
const xs = [7,2,3,6];
fp.sum(fp.filter(t => t % 2 ==0, fp.map(x => x + 1, xs)));

Lodash-fp with compose

最後に Lodash-fp の compose を使って関数合成して書いてみます。

const fp = require('lodash/fp');
const xs = [7, 2, 3, 6];
let f = fp.compose(fp.sum, fp.filter(t => t % 2 == 0), fp.map(x => x + 1))
f(xs);

compose の分だけやや長くなるけど、Haskell の関数合成の書き方に近くなりました。

まとめ

Lodash-fp の compose を使えば JavaScript でも Haskell と似たような順番で関数合成して書けます。

7
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
1