fp-tsの型クラス
fp-tsの型クラスはかなりきめ細かいmrsekut.icon
Haskellよりきめ細かいPureScriptよりも、きめ細かい
fp-tsの方がきめ細かいので、例えばMagmaとかは載っていないmrsekut.icon
具体例
etc.
Category
Applicative
Monad
code:ts
of: <A>(a: A) => HKT<M, A>
flatMap: <A, B>(f: (a: A) => HKT<M, B>) => ((ma: HKT<M, A>) => HKT<M, B>)
code:ts
chain: <A, B>(ma: HKT<M, A>, f: (a: A) => HKT<M, B>) => HKT<M, B>
table:hsとの対応
fp-ts haskell
of bind
flatMap return
chain (>>=)
型クラスとinstance
に書いてる
例えば、Eqだと
型クラスの定義
code:Eq.ts
interface Eq<A> {
readonly equals: (x: A, y: A) => boolean
}
instanceの定義
例えば、numberを見てみると、
code:ts
const Eq: E.Eq<number> = {
equals: (first, second) => first === second
}
こうやって使う
code:ts
import * as N from 'fp-ts/number';
import * as Eq from 'fp-ts/Eq';
console.log(N.Eq.equals(1, 1)); // => true
console.log(N.Eq.equals(1, 2)); // => false
この例はprimitiveすぎて逆に分かりづらいmrsekut.icon
もう少し複雑な例を見てみるといい
例えば、自作の型PointをEqのinstanceにするにはどうすればいいか?
code:ts
type Point = {
x: number
y: number
}
方法1
自分で、0から定義する
code:ts
const eqPoint: Eq.Eq<Point> = {
equals: (p1, p2) => p1.x === p2.x && p1.y === p2.y
};
方法2
用意されているcombinatorsの関数を使う
こっちの方が普通mrsekut.icon
code:ts
const eqPoint = Eq.struct<Point>({
x: N.Eq,
y: N.Eq
});
この使い方だけ見るとad hocではない
code:ts
import * as Ord from "fp-ts/Ord";
import * as S from "fp-ts/string";
import * as N from "fp-ts/number";
console.log(N.Ord.compare(1, 2)); // => -1
console.log(N.Ord.compare(1, 1)); // => 0
console.log(S.Ord.compare("a", "b")); // => -1
結局、使用する型によって、どのmoduleか(NとかSとか)を指定しないといけない
hsなら、これに関係なくOrd.compareだけ呼べば勝手に良い感じになる