emely-marchena-zXuefdR73e0-unsplash.jpg

fp-tsとMonoid

 
0
このエントリーをはてなブックマークに追加
Kazuki Moriyama
Kazuki Moriyama (森山 和樹)

単位元付きの二項演算を司る型クラスMonoidを紹介。

https://gcanti.github.io/fp-ts/modules/Monoid.ts.html

定義

interface Monoid<A> extends Semigroup<A> {
  readonly empty: A
}

定義を見ると分かる通り、すべてのMonoidはSemigroupである。

参考: Semigroupについて。

https://kazchimo.com/2021/05/30/fp-ts-semigroup/

できるのはなにか2つをとって一つを返すこと。
そして単位元がそれにひっついていること。

満たすべきlaw

concatについてはSemigroupと同様に結合律を満たす必要がある。
更にemptyについては以下のように単位元にならなければならない。

concat(x, empty) = concat(empty, x) = x

使い方

import * as S from "fp-ts/string";
import * as N from "fp-ts/number";

console.log(S.Monoid.concat("a", "b")); // => ab
console.log(N.MonoidSum.concat(2, 3)); // => 5
console.log(N.MonoidProduct.concat(2, 3)); // => 6
console.log(N.MonoidProduct.empty); // => 1
console.log(N.MonoidSum.empty); // => 0

numberに対しては和と積で作られたMonoidが用意されている。
単位元もそれぞれ異なる。

combinators

reverse

引数を入れ替えてconcatに適用するMonoidを返す。

console.log(Monoid.reverse(S.Monoid).concat("a", "b")); // => ba

struct

オブジェクトに対するMonoidを複数のMonoidから構築できる。

type Person = {
  name: string;
  age: number;
};

const personMonoid = Monoid.struct<Person>({
  name: S.Monoid,
  age: N.MonoidSum,
}); 

console.log(
  personMonoid.concat({ name: "tanaka", age: 20 }, { name: "taro", age: 10 })
); // => { name: 'tanakataro', age: 30 }

tuple

タプルのMonoidを複数のMonoidから構築できる。

const tuple3Monoid = Monoid.tuple(S.Monoid, N.MonoidSum, N.MonoidProduct);

console.log(tuple3Monoid.concat(["a", 2, 3], ["b", 4, 5])); // => [ 'ab', 6, 15 ]

constructors

max/min

Bounded<A>というある型Aにたいする上限値と下限値を定義する型クラスをとってAのMonoidインスタンスを作成する。
concatのロジックはそれぞれ大きい方、小さい方を返すだけである。

console.log(Monoid.max(N.Bounded).concat(1, 2)); // => 2
console.log(Monoid.min(N.Bounded).concat(1, 2)); // => 1

BoundedはOrdを継承しているため、Ordによる大小比較が内部的には使用されている。
ロジック的にBoundedいらなくね?と思うかもしれないが、max/minが作っているのはあくまでもMonoidであるためempty用の値が必要となる。
empty値としてBoundedの上限値、もしくは下限値が使用されている。

console.log(Monoid.max(N.Bounded).empty); // => -Infinity
console.log(Monoid.min(N.Bounded).empty); // => Infinity

utils

concatAll

Monoidを与えると配列の中身を全部concatしてくれる便利なやつ。
reduceとかの挙動のイメージ。

console.log(Monoid.concatAll(N.MonoidSum)([1, 2, 3])); // => 6
info-outline

お知らせ

K.DEVは株式会社KDOTにより運営されています。記事の内容や会社でのITに関わる一般的なご相談に専門の社員がお答えしております。ぜひお気軽にご連絡ください。