fp-tsの一覧ページがあまりにも重くなったので、分割
参照元
一覧
Functorの内容確認
参考
ファイル名 | import先 | ソースの中身 | declare module がある | importでの参照される数 |
---|---|---|---|---|
Functor |
|
interface, function のみ | なし | 12 |
満たすべきもの
恒等射、単位元
F.map(fa, x => x) = fa
射の合成、合成
F.map(fa, x => f(g(x))) = F.map(F.map(fa, g), f)
import { describe, it } from 'vitest'
import { type Functor1 } from 'fp-ts/lib/Functor'
import type { Kind, URIS } from 'fp-ts/lib/HKT'
import { pipe } from 'fp-ts/lib/function'
import * as f from 'fp-ts/function'
const URI = 'Test2'
type URI = typeof URI
declare module 'fp-ts/HKT' {
interface URItoKind<A> {
readonly Test2: Test2<A>
}
}
const Test2Functor: Functor1<URI> = {
URI,
map: (ma, f) => ({ Test2: f(ma.Test2) })
}
const Functor1Id: <F extends URIS>(Functor: Functor1<F>) => <A>(fa: Kind<F, A>) => Kind<F, A> =
(Functor) => (fa) =>
Functor.map(fa, f.identity)
const Functor1Composition1: <F extends URIS>(
Functor: Functor1<F>
) => <A, B>(g: (a: A) => B) => <C>(f: (a: B) => C) => (fa: Kind<F, A>) => Kind<F, C> =
(Functor) => (g) => (f) => (fa) =>
Functor.map(fa, (x) => f(g(x)))
const Functor1Composition2: <F extends URIS>(
Functor: Functor1<F>
) => <A, B>(g: (a: A) => B) => <C>(f: (a: B) => C) => (fa: Kind<F, A>) => Kind<F, C> =
(Functor) => (g) => (f) => (fa) =>
Functor.map(Functor.map(fa, g), f)
type Test2<XXX> = {
Test2: XXX
}
type A = number
type B = string
type C = boolean
type A2 = string
type B2 = boolean
type C2 = number
type A3 = boolean
type B3 = string
type C3 = number
type F<XXX> = Test2<XXX>
describe('fp-ts Tutorial', () => {
it('Functor', () => {
// object
const a: A = 123
const a2: A2 = 'abc'
const a3: A3 = true
const fa: F<A> = {
Test2: a
}
const fa2: F<A2> = {
Test2: a2
}
const fa3: F<A3> = {
Test2: a3
}
const a_b_function: (a: A) => B = (a) => String(a)
const b_c_function: (b: B) => C = (b) => Boolean(b)
const a2_b2_function: (a: A2) => B2 = (a) => Boolean(a)
const b2_c2_function: (b: B2) => C2 = (b) => (Number.isNaN(Number(b)) ? 0 : Number(b))
const a3_b3_function: (a: A3) => B3 = (a) => String(a)
const b3_c3_function: (b: B3) => C3 = (b) => (Number.isNaN(Number(b)) ? 0 : Number(b))
console.log('A => B => C')
console.log()
console.log('F.map(fa, x => x) - ', pipe(fa, Functor1Id(Test2Functor)))
console.log('fa - ', fa)
console.log()
console.log(
'F.map(fa, x => f(g(x))) - ',
pipe(fa, Functor1Composition1(Test2Functor)(a_b_function)(b_c_function))
)
console.log(
'F.map(F.map(fa, g), f) - ',
pipe(fa, Functor1Composition2(Test2Functor)(a_b_function)(b_c_function))
)
console.log('---------')
console.log('A2 => B2 => C2')
console.log()
console.log('F.map(fa, x => x) - ', pipe(fa2, Functor1Id(Test2Functor)))
console.log('fa - ', fa2)
console.log()
console.log(
'F.map(fa, x => f(g(x))) - ',
pipe(fa2, Functor1Composition1(Test2Functor)(a2_b2_function)(b2_c2_function))
)
console.log(
'F.map(F.map(fa, g), f) - ',
pipe(fa2, Functor1Composition2(Test2Functor)(a2_b2_function)(b2_c2_function))
)
console.log('---------')
console.log('A3 => B3 => C3')
console.log()
console.log('F.map(fa, x => x) - ', pipe(fa3, Functor1Id(Test2Functor)))
console.log('fa - ', fa3)
console.log()
console.log(
'F.map(fa, x => f(g(x))) - ',
pipe(fa3, Functor1Composition1(Test2Functor)(a3_b3_function)(b3_c3_function))
)
console.log(
'F.map(F.map(fa, g), f) - ',
pipe(fa3, Functor1Composition2(Test2Functor)(a3_b3_function)(b3_c3_function))
)
})
})
実行結果
A => B => C
F.map(fa, x => x) - { Test2: 123 }
fa - { Test2: 123 }
F.map(fa, x => f(g(x))) - { Test2: true }
F.map(F.map(fa, g), f) - { Test2: true }
---------
A2 => B2 => C2
F.map(fa, x => x) - { Test2: 'abc' }
fa - { Test2: 'abc' }
F.map(fa, x => f(g(x))) - { Test2: 1 }
F.map(F.map(fa, g), f) - { Test2: 1 }
---------
A3 => B3 => C3
F.map(fa, x => x) - { Test2: true }
fa - { Test2: true }
F.map(fa, x => f(g(x))) - { Test2: 0 }
F.map(F.map(fa, g), f) - { Test2: 0 }
Functorの法則を満たさないもの
不完全なFunctorを作成できてしまう
import { describe, it } from 'vitest'
import { type Functor1 } from 'fp-ts/lib/Functor'
import type { Kind, URIS } from 'fp-ts/lib/HKT'
import { pipe } from 'fp-ts/lib/function'
import * as f from 'fp-ts/function'
const URI = 'Test2'
type URI = typeof URI
declare module 'fp-ts/HKT' {
interface URItoKind<A> {
readonly Test2: Test2<A>
}
}
const Test2Functor: Functor1<URI> = {
URI,
map: <A, B>(ma: Kind<URI, A>, f: (a: A) => B) => {
const test: A =
typeof ma.Test2 === 'number'
? ((ma.Test2 + 1) as A)
: typeof ma.Test2 === 'string'
? ((ma.Test2 + 'a') as A)
: typeof ma.Test2 === 'boolean'
? (!ma.Test2 as A)
: ma.Test2
return { Test2: f(test) }
}
}
const Functor1Id: <F extends URIS>(Functor: Functor1<F>) => <A>(fa: Kind<F, A>) => Kind<F, A> =
(Functor) => (fa) =>
Functor.map(fa, f.identity)
const Functor1Composition1: <F extends URIS>(
Functor: Functor1<F>
) => <A, B>(g: (a: A) => B) => <C>(f: (a: B) => C) => (fa: Kind<F, A>) => Kind<F, C> =
(Functor) => (g) => (f) => (fa) =>
Functor.map(fa, (x) => f(g(x)))
const Functor1Composition2: <F extends URIS>(
Functor: Functor1<F>
) => <A, B>(g: (a: A) => B) => <C>(f: (a: B) => C) => (fa: Kind<F, A>) => Kind<F, C> =
(Functor) => (g) => (f) => (fa) =>
Functor.map(Functor.map(fa, g), f)
type Test2<XXX> = {
Test2: XXX
}
type A = number
type B = string
type C = boolean
type A2 = string
type B2 = boolean
type C2 = number
type A3 = boolean
type B3 = string
type C3 = number
type F<XXX> = Test2<XXX>
describe('fp-ts Tutorial', () => {
it('Functor', () => {
// object
const a: A = 123
const a2: A2 = 'abc'
const a3: A3 = true
const fa: F<A> = {
Test2: a
}
const fa2: F<A2> = {
Test2: a2
}
const fa3: F<A3> = {
Test2: a3
}
const a_b_function: (a: A) => B = (a) => String(a)
const b_c_function: (b: B) => C = (b) => Boolean(b)
const a2_b2_function: (a: A2) => B2 = (a) => Boolean(a)
const b2_c2_function: (b: B2) => C2 = (b) => (Number.isNaN(Number(b)) ? 0 : Number(b))
const a3_b3_function: (a: A3) => B3 = (a) => String(a)
const b3_c3_function: (b: B3) => C3 = (b) => (Number.isNaN(Number(b)) ? 0 : Number(b))
console.log('A => B => C')
console.log()
console.log('F.map(fa, x => x) - ', pipe(fa, Functor1Id(Test2Functor)))
console.log('fa - ', fa)
console.log()
console.log(
'F.map(fa, x => f(g(x))) - ',
pipe(fa, Functor1Composition1(Test2Functor)(a_b_function)(b_c_function))
)
console.log(
'F.map(F.map(fa, g), f) - ',
pipe(fa, Functor1Composition2(Test2Functor)(a_b_function)(b_c_function))
)
console.log('---------')
console.log('A2 => B2 => C2')
console.log()
console.log('F.map(fa, x => x) - ', pipe(fa2, Functor1Id(Test2Functor)))
console.log('fa - ', fa2)
console.log()
console.log(
'F.map(fa, x => f(g(x))) - ',
pipe(fa2, Functor1Composition1(Test2Functor)(a2_b2_function)(b2_c2_function))
)
console.log(
'F.map(F.map(fa, g), f) - ',
pipe(fa2, Functor1Composition2(Test2Functor)(a2_b2_function)(b2_c2_function))
)
console.log('---------')
console.log('A3 => B3 => C3')
console.log()
console.log('F.map(fa, x => x) - ', pipe(fa3, Functor1Id(Test2Functor)))
console.log('fa - ', fa3)
console.log()
console.log(
'F.map(fa, x => f(g(x))) - ',
pipe(fa3, Functor1Composition1(Test2Functor)(a3_b3_function)(b3_c3_function))
)
console.log(
'F.map(F.map(fa, g), f) - ',
pipe(fa3, Functor1Composition2(Test2Functor)(a3_b3_function)(b3_c3_function))
)
})
})
実行結果
A => B => C
F.map(fa, x => x) - { Test2: 124 }
fa - { Test2: 123 }
F.map(fa, x => f(g(x))) - { Test2: true }
F.map(F.map(fa, g), f) - { Test2: true }
---------
A2 => B2 => C2
F.map(fa, x => x) - { Test2: 'abca' }
fa - { Test2: 'abc' }
F.map(fa, x => f(g(x))) - { Test2: 1 }
F.map(F.map(fa, g), f) - { Test2: 0 }
---------
A3 => B3 => C3
F.map(fa, x => x) - { Test2: false }
fa - { Test2: true }
F.map(fa, x => f(g(x))) - { Test2: 0 }
F.map(F.map(fa, g), f) - { Test2: 0 }
Functorの利用
import { describe, it } from 'vitest'
import { type Functor1 } from 'fp-ts/lib/Functor'
// import type { Kind, URIS } from 'fp-ts/lib/HKT'
import { pipe } from 'fp-ts/lib/function'
// import * as f from 'fp-ts/function'
import * as F from 'fp-ts/Functor'
const URI2 = 'Test2'
type URI2 = typeof URI2
const URI3 = 'Test3'
type URI3 = typeof URI3
type Test2<XXX> = {
Test2: XXX
}
type Test3<XXX> = {
Test3: XXX[]
}
declare module 'fp-ts/HKT' {
interface URItoKind<A> {
readonly Test2: Test2<A>
readonly Test3: Test3<A>
}
}
const Test2Functor: Functor1<URI2> = {
URI: URI2,
map: (ma, f) => ({ Test2: f(ma.Test2) })
}
const Test3Functor: Functor1<URI3> = {
URI: URI3,
map: (ma, f) => ({ Test3: ma.Test3.map(f) })
}
// const Functor1Id: <FFF extends URIS>(
// Functor: Functor1<FFF>
// ) => <XXX>(fa: Kind<FFF, XXX>) => Kind<FFF, XXX> = (Functor) => (fa) => Functor.map(fa, f.identity)
// const Functor1Composition1: <FFF extends URIS>(
// Functor: Functor1<FFF>
// ) => <XXX, YYY>(
// g: (x: XXX) => YYY
// ) => <ZZZ>(f: (y: YYY) => ZZZ) => (fx: Kind<FFF, XXX>) => Kind<FFF, ZZZ> =
// (Functor) => (g) => (f) => (fa) =>
// Functor.map(fa, (x) => f(g(x)))
// const Functor1Composition2: <FFF extends URIS>(
// Functor: Functor1<FFF>
// ) => <XXX, YYY>(
// g: (x: XXX) => YYY
// ) => <ZZZ>(f: (y: YYY) => ZZZ) => (fx: Kind<FFF, XXX>) => Kind<FFF, ZZZ> =
// (Functor) => (g) => (f) => (fa) =>
// Functor.map(Functor.map(fa, g), f)
type A = number
type B = string
// type C = boolean
type F2<XXX> = Test2<XXX>
type F3<XXX> = Test3<XXX>
type F<XXX> = Test3<Test2<XXX>>
describe('fp-ts Tutorial', () => {
it('Functor', () => {
// object
const a123: A = 123
const a456: A = 456
const a789: A = 789
const fa2_123: F2<A> = {
Test2: a123
}
const fa2_456: F2<A> = {
Test2: a456
}
const fa2_789: F2<A> = {
Test2: a789
}
const fa3: F3<A> = {
Test3: [a123, a456, a789]
}
const fa: F<A> = {
Test3: [fa2_123, fa2_456, fa2_789]
}
const a_b_function: (a: A) => B = (a) => String(a)
// const b_c_function: (b: B) => C = (b) => Boolean(b)
const fa2_function_object: F2<(a: A) => B> = {
Test2: a_b_function
}
const fa3_function_object: F3<(a: A) => B> = {
Test3: [a_b_function, (a) => a_b_function(2 * a), (a) => a_b_function(3 * a)]
}
// // check
// console.log('---- check -----')
// console.log('Test2Functor')
// console.log()
// console.log('A => B => C')
// console.log()
// console.log('F.map(fa, x => x) - ', pipe(fa2, Functor1Id(Test2Functor)))
// console.log('fa - ', fa2)
// console.log()
// console.log(
// 'F.map(fa, x => f(g(x))) - ',
// pipe(fa2, Functor1Composition1(Test2Functor)(a_b_function)(b_c_function))
// )
// console.log(
// 'F.map(F.map(fa, g), f) - ',
// pipe(fa2, Functor1Composition2(Test2Functor)(a_b_function)(b_c_function))
// )
// console.log('---------')
// console.log()
// console.log('Test2Functor')
// console.log()
// console.log('A => B => C')
// console.log()
// console.log('F.map(fa, x => x) - ', pipe(fa3, Functor1Id(Test3Functor)))
// console.log('fa - ', fa3)
// console.log()
// console.log(
// 'F.map(fa, x => f(g(x))) - ',
// pipe(fa3, Functor1Composition1(Test3Functor)(a_b_function)(b_c_function))
// )
// console.log(
// 'F.map(F.map(fa, g), f) - ',
// pipe(fa3, Functor1Composition2(Test3Functor)(a_b_function)(b_c_function))
// )
// console.log('---------')
// console.log()
// test
console.log('map - ', pipe(fa, F.map(Test3Functor, Test2Functor)(a_b_function)))
console.log('flap - Test2Functor - ', F.flap(Test2Functor)(a123)(fa2_function_object))
console.log('flap - Test3Functor - ', F.flap(Test3Functor)(a123)(fa3_function_object))
console.log('bindTo - Test2Functor - ', pipe(fa2_123, F.bindTo(Test2Functor)('Test BindTo')))
console.log('bindTo - Test3Functor - ', pipe(fa3, F.bindTo(Test3Functor)('Test BindTo')))
console.log(
'let - Test2Functor - ',
pipe(fa2_123, F.let(Test2Functor)('Test Let', a_b_function))
)
console.log('let - Test3Functor - ', pipe(fa3, F.let(Test3Functor)('Test Let', a_b_function)))
})
})
実行結果
map - { Test3: [ { Test2: '123' }, { Test2: '456' }, { Test2: '789' } ] }
flap - Test2Functor - { Test2: '123' }
flap - Test3Functor - { Test3: [ '123', '246', '369' ] }
bindTo - Test2Functor - { Test2: { 'Test BindTo': 123 } }
bindTo - Test3Functor - {
Test3: [
{ 'Test BindTo': 123 },
{ 'Test BindTo': 456 },
{ 'Test BindTo': 789 }
]
}
let - Test2Functor - { Test2: { 'Test Let': '123' } }
let - Test3Functor - {
Test3: [
{ 'Test Let': '123' },
{ 'Test Let': '456' },
{ 'Test Let': '789' }
]
}