diff --git a/README.md b/README.md index 39d0f7c..f4570ac 100644 --- a/README.md +++ b/README.md @@ -32,9 +32,7 @@ const employee: Employee = { } } -function capitalize(s: string): string { - return s.substring(0, 1).toUpperCase() + s.substring(1) -} +const capitalize = (s: string): string => s.substring(0, 1).toUpperCase() + s.substring(1) const employee2 = { ...employee, @@ -73,7 +71,7 @@ company .compose(address) .compose(street) .compose(name) - .modify(capitalize, employee) + .modify(capitalize)(employee) ``` Here `modify` lift a function `string => string` to a function `Employee => Employee`. It works but it would be clearer if we could zoom @@ -86,7 +84,7 @@ import { some, none } from 'fp-ts/lib/Option' const firstLetter = new Optional( s => s.length > 0 ? some(s[0]) : none, - (a, s) => a + s.substring(1) + a => s => a + s.substring(1) ) company @@ -95,7 +93,7 @@ company .compose(name) .asOptional() .compose(firstLetter) - .modify(s => s.toUpperCase(), employee) + .modify(s => s.toUpperCase())(employee) ``` Similarly to `compose` for lenses, `compose` for optionals takes two `Optionals`, one from `A` to `B` and another from `B` to `C` and creates a third `Optional` from `A` to `C`. diff --git a/examples/Fold.ts b/examples/Fold.ts index cace4d5..39baebe 100644 --- a/examples/Fold.ts +++ b/examples/Fold.ts @@ -4,7 +4,12 @@ import { monoidProduct, monoidSum } from 'fp-ts/lib/Monoid' import { identity } from 'fp-ts/lib/function' const xs = ['a', 'bb'] -const fold = fromFoldable(array) +const fold = fromFoldable(array)() +const len = (s: string) => s.length -console.log(fold.foldMap(monoidSum, s => s.length, xs)) -console.log(fold.foldMap(monoidProduct, s => s.length, xs)) +console.log(fold.foldMap(monoidSum)(len)(xs)) +console.log(fold.foldMap(monoidProduct)(len)(xs)) + +import * as either from 'fp-ts/lib/Either' + +const fold2 = fromFoldable(either)() diff --git a/examples/Lens.ts b/examples/Lens.ts index 179ca55..57200ca 100644 --- a/examples/Lens.ts +++ b/examples/Lens.ts @@ -31,13 +31,13 @@ export const employee: Employee = { } } -const company = new Lens(s => s.company, (a, s) => ({ ...s, company: a })) +const company = new Lens(s => s.company, a => s => ({ ...s, company: a })) console.log(JSON.stringify(company.get(employee), null, 2)) -const address = new Lens(s => s.address, (a, s) => ({ ...s, address: a })) -const street = new Lens(s => s.street, (a, s) => ({ ...s, street: a })) -const name = new Lens(s => s.name, (a, s) => ({ ...s, name: a })) +const address = new Lens(s => s.address, a => s => ({ ...s, address: a })) +const street = new Lens(s => s.street, a => s => ({ ...s, street: a })) +const name = new Lens(s => s.name, a => s => ({ ...s, name: a })) // composition const streetLens = company.compose(address).compose(street) @@ -45,17 +45,17 @@ export const nameLens = streetLens.compose(name) console.log(JSON.stringify(nameLens.get(employee), null, 2)) -const employee2 = nameLens.modify(a => a.toUpperCase(), employee) +const employee2 = nameLens.modify(a => a.toUpperCase())(employee) console.log(JSON.stringify(employee2, null, 2)) -const employee3 = nameLens.set('low street', employee) +const employee3 = nameLens.set('low street')(employee) console.log(JSON.stringify(employee3, null, 2)) -const numLens = streetLens.compose(new Lens(s => s.num, (a, s) => ({ ...s, num: a }))) +const numLens = streetLens.compose(new Lens(s => s.num, a => s => ({ ...s, num: a }))) -console.log(JSON.stringify(numLens.set(42, employee), null, 2)) +console.log(JSON.stringify(numLens.set(42)(employee), null, 2)) // generation type PersonType = { @@ -67,4 +67,4 @@ const person: PersonType = { name: 'Giulio', age: 42 } const age = Lens.fromProp('age') -console.log(age.set(43, person)) // => { name: 'Giulio', age: 43 } +console.log(age.set(43)(person)) // => { name: 'Giulio', age: 43 } diff --git a/examples/Optional.ts b/examples/Optional.ts index 0591a32..cd4903f 100644 --- a/examples/Optional.ts +++ b/examples/Optional.ts @@ -4,17 +4,17 @@ import { nameLens, employee } from './Lens' const head = new Optional( s => (s.length > 0 ? some(s[0]) : none), - (a, s) => (s.length > 0 ? a + s.substring(1) : '') + a => s => (s.length > 0 ? a + s.substring(1) : '') ) console.log(head.getOption('')) // => None console.log(head.getOption('hello')) // => Some('h') -console.log(head.set('H', '')) // => '' -console.log(head.set('H', 'hello')) // => 'Hello' +console.log(head.set('H')('')) // => '' +console.log(head.set('H')('hello')) // => 'Hello' const optional = nameLens.asOptional().compose(head) -console.log(JSON.stringify(optional.modify(s => s.toUpperCase(), employee), null, 2)) +console.log(JSON.stringify(optional.modify(s => s.toUpperCase())(employee), null, 2)) interface Person { name: string @@ -26,4 +26,4 @@ const surname = Lens.fromProp('surname').composePrism(Prism.s const p: Person = { name: 'Giulio', surname: none } console.log(surname.getOption(p)) // => None -console.log(surname.set('Canti', p)) // => { name: 'Giulio', surname: Some("Canti") } +console.log(surname.set('Canti')(p)) // => { name: 'Giulio', surname: Some("Canti") } diff --git a/examples/Prism.ts b/examples/Prism.ts index b7b169a..011331d 100644 --- a/examples/Prism.ts +++ b/examples/Prism.ts @@ -20,10 +20,10 @@ console.log(jStr.getOption(new JNum(1))) // a function is applied only if there is a match const reverse = (s: string): string => s.split('').reverse().join('') -console.log(jStr.modify(reverse, new JStr('hello'))) -console.log(jStr.modify(reverse, new JNum(1))) -console.log(jStr.modifyOption(reverse, new JStr('hello'))) -console.log(jStr.modifyOption(reverse, new JNum(1))) +console.log(jStr.modify(reverse)(new JStr('hello'))) +console.log(jStr.modify(reverse)(new JNum(1))) +console.log(jStr.modifyOption(reverse)(new JStr('hello'))) +console.log(jStr.modifyOption(reverse)(new JNum(1))) // composizione const jNum = new Prism(s => (s instanceof JNum ? some(s.value) : none), a => new JNum(a)) diff --git a/examples/Traversal.ts b/examples/Traversal.ts index cbb6d32..941bb9c 100644 --- a/examples/Traversal.ts +++ b/examples/Traversal.ts @@ -1,17 +1,17 @@ import { fromTraversable } from '../src' import { array } from 'fp-ts/lib/Array' -const eachL = fromTraversable(array) +const eachL = fromTraversable(array)() const xs = [1, 2, 3, 4] -console.log(eachL.set(0, xs)) // => [ 0, 0, 0, 0 ] +console.log(eachL.set(0)(xs)) // => [ 0, 0, 0, 0 ] -console.log(eachL.modify((n: number) => n + 1, xs)) // => [ 2, 3, 4, 5 ] +console.log(eachL.modify((n: number) => n + 1)(xs)) // => [ 2, 3, 4, 5 ] const fold = eachL.asFold() console.log(fold.getAll(xs)) console.log(fold.headOption(xs)) -console.log(fold.find(n => n > 2, xs)) -console.log(fold.all((n: number) => n % 2 === 0, xs)) +console.log(fold.find(n => n > 2)(xs)) +console.log(fold.all((n: number) => n % 2 === 0)(xs)) diff --git a/examples/introduction.ts b/examples/introduction.ts index f8bedad..7c7cb38 100644 --- a/examples/introduction.ts +++ b/examples/introduction.ts @@ -58,7 +58,7 @@ const name = Lens.fromProp('name') import { some, none } from 'fp-ts/lib/Option' -const firstLetter = new Optional(s => (s.length > 0 ? some(s[0]) : none), (a, s) => a + s.substring(1)) +const firstLetter = new Optional(s => (s.length > 0 ? some(s[0]) : none), a => s => a + s.substring(1)) console.log( JSON.stringify( @@ -68,7 +68,7 @@ console.log( .compose(name) .asOptional() .compose(firstLetter) - .modify(s => s.toUpperCase(), employee), + .modify(s => s.toUpperCase())(employee), null, 2 ) diff --git a/package.json b/package.json index 363b739..65217e9 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ }, "homepage": "https://github.com/gcanti/monocle-ts", "dependencies": { - "fp-ts": "^0.4.3" + "fp-ts": "^0.5.0" }, "devDependencies": { "@types/mocha": "^2.2.38", diff --git a/src/index.ts b/src/index.ts index e1de92f..9487d48 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,13 +1,13 @@ -import { HKT } from 'fp-ts/lib/HKT' +import { HKT, HKTS, HKTAs, HKT2S, HKT2As } from 'fp-ts/lib/HKT' import { Monoid, monoidArray, monoidAll, monoidAny } from 'fp-ts/lib/Monoid' import { Applicative } from 'fp-ts/lib/Applicative' import { Foldable, foldMap } from 'fp-ts/lib/Foldable' import { Traversable } from 'fp-ts/lib/Traversable' import * as option from 'fp-ts/lib/Option' import { Option, none, some } from 'fp-ts/lib/Option' -import { identity, constant, Predicate } from 'fp-ts/lib/function' +import { identity, constant, Predicate, Endomorphism } from 'fp-ts/lib/function' import * as id from 'fp-ts/lib/Identity' -import * as con from 'fp-ts/lib/Const' +import * as const_ from 'fp-ts/lib/Const' /* Laws: @@ -16,15 +16,15 @@ import * as con from 'fp-ts/lib/Const' */ export class Iso { readonly _tag: 'Iso' = 'Iso' - constructor(public get: (s: S) => A, public reverseGet: (a: A) => S) {} + constructor(readonly get: (s: S) => A, readonly reverseGet: (a: A) => S) {} - modify(f: (a: A) => A, s: S): S { - return this.reverseGet(f(this.get(s))) + modify(f: Endomorphism): Endomorphism { + return s => this.reverseGet(f(this.get(s))) } /** view an Iso as a Lens */ asLens(): Lens { - return new Lens(this.get, this.reverseGet) + return new Lens(this.get, a => s => this.reverseGet(a)) } /** view an Iso as a Prism */ @@ -34,29 +34,29 @@ export class Iso { /** view an Iso as a Optional */ asOptional(): Optional { - return new Optional(s => some(this.get(s)), (a, s) => this.reverseGet(a)) + return new Optional(s => some(this.get(s)), a => s => this.reverseGet(a)) } /** view an Iso as a Traversal */ asTraversal(): Traversal { - return new Traversal((F: Applicative, f: (a: A) => HKT, s: S): HKT => - F.map((a: A) => this.reverseGet(a), f(this.get(s))) + return new Traversal((F: Applicative) => (f: (a: A) => HKT) => s => + F.map(a => this.reverseGet(a), f(this.get(s))) ) } /** view an Iso as a Fold */ asFold(): Fold { - return new Fold((M: Monoid, f: (a: A) => M, s: S): M => f(this.get(s))) + return new Fold((M: Monoid) => (f: (a: A) => M) => s => f(this.get(s))) } /** view an Iso as a Getter */ asGetter(): Getter { - return new Getter((s: S) => this.get(s)) + return new Getter(s => this.get(s)) } /** view an Iso as a Setter */ asSetter(): Setter { - return new Setter((f: (a: A) => A, s: S) => this.modify(f, s)) + return new Setter(f => s => this.modify(f)(s)) } /** compose an Iso with an Iso */ @@ -189,15 +189,15 @@ export function lensFromPath(path: Array) { export class Lens { static fromPath = lensFromPath readonly _tag: 'Lens' = 'Lens' - constructor(public get: (s: S) => A, public set: (a: A, s: S) => S) {} + constructor(readonly get: (s: S) => A, readonly set: (a: A) => Endomorphism) {} /** generate a lens from a type and a prop */ static fromProp(prop: P): Lens { - return new Lens(s => s[prop], (a, s) => Object.assign({}, s, { [prop as any]: a })) + return new Lens(s => s[prop], a => s => Object.assign({}, s, { [prop as any]: a })) } - modify(f: (a: A) => A, s: S): S { - return this.set(f(this.get(s)), s) + modify(f: Endomorphism): Endomorphism { + return s => this.set(f(this.get(s)))(s) } /** view a Lens as a Optional */ @@ -207,29 +207,29 @@ export class Lens { /** view a Lens as a Traversal */ asTraversal(): Traversal { - return new Traversal((F: Applicative, f: (a: A) => HKT, s: S): HKT => - F.map(a => this.set(a, s), f(this.get(s))) + return new Traversal((F: Applicative) => (f: (a: A) => HKT) => s => + F.map(a => this.set(a)(s), f(this.get(s))) ) } /** view a Lens as a Setter */ asSetter(): Setter { - return new Setter((f, s) => this.modify(f, s)) + return new Setter(f => s => this.modify(f)(s)) } /** view a Lens as a Getter */ asGetter(): Getter { - return new Getter(s => this.get(s)) + return new Getter(s => this.get(s)) } /** view a Lens as a Fold */ asFold(): Fold { - return new Fold((M: Monoid, f: (a: A) => M, s: S): M => f(this.get(s))) + return new Fold((M: Monoid) => (f: (a: A) => M) => s => f(this.get(s))) } /** compose a Lens with a Lens */ compose(ab: Lens): Lens { - return new Lens(s => ab.get(this.get(s)), (b, s) => this.set(ab.set(b, this.get(s)), s)) + return new Lens(s => ab.get(this.get(s)), b => s => this.set(ab.set(b)(this.get(s)))(s)) } /** compose a Lens with a Getter */ @@ -275,7 +275,7 @@ export class Lens { */ export class Prism { readonly _tag: 'Prism' = 'Prism' - constructor(public getOption: (s: S) => Option, public reverseGet: (a: A) => S) {} + constructor(readonly getOption: (s: S) => Option, readonly reverseGet: (a: A) => S) {} static fromPredicate(predicate: Predicate): Prism { return new Prism(s => (predicate(s) ? some(s) : none), a => a) @@ -285,34 +285,34 @@ export class Prism { return somePrism } - modify(f: (a: A) => A, s: S): S { - return this.modifyOption(f, s).fold(constant(s), identity) + modify(f: Endomorphism): Endomorphism { + return s => this.modifyOption(f)(s).fold(constant(s), identity) } - modifyOption(f: (a: A) => A, s: S): Option { - return this.getOption(s).map(a => this.reverseGet(f(a))) + modifyOption(f: Endomorphism): (s: S) => Option { + return s => this.getOption(s).map(a => this.reverseGet(f(a))) } /** view a Prism as a Optional */ asOptional(): Optional { - return new Optional(this.getOption, this.reverseGet) + return new Optional(this.getOption, a => s => this.reverseGet(a)) } /** view a Prism as a Traversal */ asTraversal(): Traversal { - return new Traversal((F: Applicative, f: (a: A) => HKT, s: S): HKT => + return new Traversal((F: Applicative) => (f: (a: A) => HKT) => s => this.getOption(s).fold(() => F.of(s), a => F.map(fa => this.reverseGet(a), f(a))) ) } /** view a Prism as a Setter */ asSetter(): Setter { - return new Setter((f, s) => this.modify(f, s)) + return new Setter(f => s => this.modify(f)(s)) } /** view a Prism as a Fold */ asFold(): Fold { - return new Fold((M: Monoid, f: (a: A) => M, s: S): M => this.getOption(s).fold(() => M.empty(), f)) + return new Fold((M: Monoid) => (f: (a: A) => M) => s => this.getOption(s).fold(() => M.empty(), f)) } /** compose a Prism with a Prism */ @@ -356,7 +356,7 @@ export class Prism { } } -const somePrism = new Prism, any>(s => s, a => some(a)) +const somePrism = new Prism, never>(s => s, a => some(a)) /* Laws: @@ -366,38 +366,38 @@ const somePrism = new Prism, any>(s => s, a => some(a)) */ export class Optional { readonly _tag: 'Optional' = 'Optional' - constructor(public getOption: (s: S) => Option, public set: (a: A, s: S) => S) {} + constructor(readonly getOption: (s: S) => Option, readonly set: (a: A) => Endomorphism) {} - modify(f: (a: A) => A, s: S): S { - return this.modifyOption(f, s).fold(constant(s), identity) + modify(f: Endomorphism): Endomorphism { + return s => this.modifyOption(f)(s).fold(constant(s), identity) } - modifyOption(f: (a: A) => A, s: S): Option { - return this.getOption(s).map(a => this.set(f(a), s)) + modifyOption(f: Endomorphism): (s: S) => Option { + return s => this.getOption(s).map(a => this.set(f(a))(s)) } /** view a Optional as a Traversal */ asTraversal(): Traversal { - return new Traversal((F: Applicative, f: (a: A) => HKT, s: S): HKT => - this.getOption(s).fold(() => F.of(s), a => F.map((a: A) => this.set(a, s), f(a))) + return new Traversal((F: Applicative) => (f: (a: A) => HKT) => s => + this.getOption(s).fold(() => F.of(s), a => F.map((a: A) => this.set(a)(s), f(a))) ) } /** view an Optional as a Fold */ asFold(): Fold { - return new Fold((M: Monoid, f: (a: A) => M, s: S): M => this.getOption(s).fold(() => M.empty(), f)) + return new Fold((M: Monoid) => (f: (a: A) => M) => s => this.getOption(s).fold(() => M.empty(), f)) } /** view an Optional as a Setter */ asSetter(): Setter { - return new Setter((f, s) => this.modify(f, s)) + return new Setter(f => s => this.modify(f)(s)) } /** compose a Optional with a Optional */ compose(ab: Optional): Optional { return new Optional( s => this.getOption(s).chain(a => ab.getOption(a)), - (b, s) => this.modify(a => ab.set(b, a), s) + b => s => this.modify(a => ab.set(b)(a))(s) ) } @@ -441,33 +441,33 @@ export class Traversal { readonly _tag: 'Traversal' = 'Traversal' constructor( // Van Laarhoven representation - public modifyF: (F: Applicative, f: (a: A) => HKT, s: S) => HKT + readonly modifyF: (F: Applicative) => (f: (a: A) => HKT) => (s: S) => HKT ) {} - modify(f: (a: A) => A, s: S): S { - return (this.modifyF(id, a => id.of(f(a)), s) as id.Identity).extract() + modify(f: Endomorphism): Endomorphism { + return s => (this.modifyF(id)(a => id.of(f(a)))(s) as id.Identity).extract() } - set(a: A, s: S): S { - return this.modify(constant(a), s) + set(a: A): Endomorphism { + return s => this.modify(constant(a))(s) } /** view a Traversal as a Fold */ asFold(): Fold { - return new Fold((M: Monoid, f: (a: A) => M, s: S): M => - (this.modifyF(con.getApplicative(M), a => new con.Const(f(a)), s) as con.Const).fold(identity) + return new Fold((M: Monoid) => (f: (a: A) => M) => s => + (this.modifyF(const_.getApplicative(M))(a => new const_.Const(f(a)))(s) as const_.Const).fold(identity) ) } /** view a Traversal as a Setter */ asSetter(): Setter { - return new Setter((f, s) => this.modify(f, s)) + return new Setter(f => s => this.modify(f)(s)) } /** compose a Traversal with a Traversal */ compose(ab: Traversal): Traversal { - return new Traversal((F: Applicative, f: (a: B) => HKT, s: S): HKT => - this.modifyF(F, a => ab.modifyF(F, f, a), s) + return new Traversal((F: Applicative) => (f: (a: B) => HKT) => (s: S): HKT => + this.modifyF(F)(a => ab.modifyF(F)(f)(a))(s) ) } @@ -509,16 +509,16 @@ export class Traversal { export class Getter { readonly _tag: 'Getter' = 'Getter' - constructor(public get: (s: S) => A) {} + constructor(readonly get: (s: S) => A) {} /** view a Getter as a Fold */ asFold(): Fold { - return new Fold((M: Monoid, f: (a: A) => M, s: S): M => f(this.get(s))) + return new Fold((M: Monoid) => (f: (a: A) => M) => s => f(this.get(s))) } /** compose a Getter with a Getter */ compose(ab: Getter): Getter { - return new Getter((s: S) => ab.get(this.get(s))) + return new Getter(s => ab.get(this.get(s))) } /** compose a Getter with a Fold */ @@ -554,11 +554,19 @@ export class Getter { export class Fold { readonly _tag: 'Fold' = 'Fold' - constructor(public foldMap: (M: Monoid, f: (a: A) => M, s: S) => M) {} + + private foldMapFirst: (f: (a: A) => Option) => (s: S) => Option + + constructor(readonly foldMap: (M: Monoid) => (f: (a: A) => M) => (s: S) => M) { + this.getAll = foldMap(monoidArray)(a => [a]) + this.exist = foldMap(monoidAny) + this.all = foldMap(monoidAll) + this.foldMapFirst = foldMap(option.getFirstMonoid()) + } /** compose a Fold with a Fold */ compose(ab: Fold): Fold { - return new Fold((M: Monoid, f: (b: B) => M, s: S): M => this.foldMap(M, a => ab.foldMap(M, f, a), s)) + return new Fold((M: Monoid) => (f: (b: B) => M) => (s: S): M => this.foldMap(M)(a => ab.foldMap(M)(f)(a))(s)) } /** compose a Fold with a Getter */ @@ -591,43 +599,37 @@ export class Fold { return this.compose(ab.asFold()) } - /** get all the targets of a Fold */ - getAll(s: S): Array { - return this.foldMap(monoidArray, a => [a], s) - } - /** find the first target of a Fold matching the predicate */ - find(p: Predicate, s: S): Option { - return this.foldMap(option.getFirstMonoid(), a => (p(a) ? option.of(a) : option.none), s) + find(p: Predicate): (s: S) => Option { + return this.foldMapFirst(a => (p(a) ? option.of(a) : option.none)) } /** get the first target of a Fold */ headOption(s: S): Option { - return this.find(() => true, s) + return this.find(() => true)(s) } +} +export interface Fold { + /** get all the targets of a Fold */ + getAll(s: S): Array /** check if at least one target satisfies the predicate */ - exist(p: Predicate, s: S): boolean { - return this.foldMap(monoidAny, p, s) - } - + exist(p: Predicate): Predicate /** check if all targets satisfy the predicate */ - all(p: Predicate, s: S): boolean { - return this.foldMap(monoidAll, p, s) - } + all(p: Predicate): Predicate } export class Setter { readonly _tag: 'Setter' = 'Setter' - constructor(public modify: (f: (a: A) => A, s: S) => S) {} + constructor(readonly modify: (f: Endomorphism) => Endomorphism) {} - set(a: A, s: S): S { - return this.modify(constant(a), s) + set(a: A): Endomorphism { + return s => this.modify(constant(a))(s) } /** compose a Setter with a Setter */ compose(ab: Setter): Setter { - return new Setter((f: (b: B) => B, s: S) => this.modify((a: A) => ab.modify(f, a), s)) + return new Setter(f => s => this.modify((a: A) => ab.modify(f)(a))(s)) } /** compose a Setter with a Traversal */ @@ -658,17 +660,20 @@ export class Setter { export class Ops { /** create a Traversal from a Traversable */ - fromTraversable(T: Traversable): Traversal, A> - fromTraversable(T: Traversable): Traversal, A> { - return new Traversal((F: Applicative, f: (a: A) => HKT, s: HKT): HKT> => - T.traverse(F)(f, s) - ) + fromTraversable(T: Traversable): () => Traversal, A> + fromTraversable(T: Traversable): () => Traversal, A> + fromTraversable(T: Traversable): () => Traversal, A> + fromTraversable(T: Traversable): () => Traversal, A> { + return () => + new Traversal, A>((F: Applicative) => (f: (a: A) => HKT) => s => T.traverse(F)(f, s)) } /** create a Fold from a Foldable */ - fromFoldable(F: Foldable): Fold, A> - fromFoldable(F: Foldable): Fold, A> { - return new Fold((M: Monoid, f: (a: A) => M, s: HKT): M => foldMap(F, M)(f, s)) + fromFoldable(F: Foldable): () => Fold, A> + fromFoldable(F: Foldable): () => Fold, A> + fromFoldable(F: Foldable): () => Fold, A> + fromFoldable(F: Foldable): () => Fold, A> { + return () => new Fold, A>((M: Monoid) => (f: (a: A) => M) => s => foldMap(F, M)(f)(s)) } } diff --git a/test/Fold.ts b/test/Fold.ts new file mode 100644 index 0000000..0dce5ce --- /dev/null +++ b/test/Fold.ts @@ -0,0 +1,30 @@ +import { Getter } from '../src' +import * as assert from 'assert' +import { some, none } from 'fp-ts/lib/Option' + +type Point = { x: number; y: number } + +const _x = new Getter((p: Point): number => p.x) + +describe('Fold', () => { + const eg0 = { x: 42, y: -1 } + + it('getAll', () => { + assert.deepEqual(_x.asFold().getAll(eg0), [42]) + }) + + it('find', () => { + assert.deepEqual(_x.asFold().find(n => n >= 42)(eg0), some(42)) + assert.deepEqual(_x.asFold().find(n => n < 42)(eg0), none) + }) + + it('exist', () => { + assert.deepEqual(_x.asFold().exist(n => n >= 42)(eg0), true) + assert.deepEqual(_x.asFold().exist(n => n < 42)(eg0), false) + }) + + it('all', () => { + assert.deepEqual(_x.asFold().all(n => n >= 42)(eg0), true) + assert.deepEqual(_x.asFold().all(n => n < 42)(eg0), false) + }) +}) diff --git a/test/Iso.ts b/test/Iso.ts index 174bdcc..a5f4412 100644 --- a/test/Iso.ts +++ b/test/Iso.ts @@ -15,7 +15,7 @@ describe('Iso', () => { it('modify', () => { const double = (x: number) => x * 2 - assert.strictEqual(mTokm.modify(double, 1000), 2000) + assert.strictEqual(mTokm.modify(double)(1000), 2000) }) it('compose', () => { diff --git a/test/Lens.ts b/test/Lens.ts index a0bbb12..7f99327 100644 --- a/test/Lens.ts +++ b/test/Lens.ts @@ -44,6 +44,6 @@ describe('Lens', () => { 'street', 'name' ]) - assert.strictEqual(lens.modify(capitalize, employee).company.address.street.name, 'High street') + assert.strictEqual(lens.modify(capitalize)(employee).company.address.street.name, 'High street') }) }) diff --git a/test/Optional.ts b/test/Optional.ts index 82a07db..81a4373 100644 --- a/test/Optional.ts +++ b/test/Optional.ts @@ -6,7 +6,7 @@ type A = { a: Option } -const optional = new Optional(s => s.a, (a, s) => s.a.fold(() => s, () => ({ ...s, a: some(a) }))) +const optional = new Optional(s => s.a, a => s => s.a.fold(() => s, () => ({ ...s, a: some(a) }))) describe('Optional', () => { it('getOption', () => { @@ -15,6 +15,6 @@ describe('Optional', () => { }) it('set', () => { - eq(optional.set(2, { a: some(1) }).a, some(2)) + eq(optional.set(2)({ a: some(1) }).a, some(2)) }) }) diff --git a/test/Prism.ts b/test/Prism.ts index cdaa7b9..37e2702 100644 --- a/test/Prism.ts +++ b/test/Prism.ts @@ -38,17 +38,17 @@ describe('Prism', () => { const sOptional = barLens.composePrism(Prism.some()).composeLens(sLens).composePrism(Prism.some()) - assert.deepEqual(sOptional.set('b', foo1), { + assert.deepEqual(sOptional.set('b')(foo1), { bar: some({ s: some('b') }) }) - assert.deepEqual(sOptional.set('c', foo2), { + assert.deepEqual(sOptional.set('c')(foo2), { bar: some({ s: some('c') }) }) - assert.deepEqual(sOptional.set('d', foo3), { + assert.deepEqual(sOptional.set('d')(foo3), { bar: none }) }) diff --git a/test/Setter.ts b/test/Setter.ts index e1a2340..fad6876 100644 --- a/test/Setter.ts +++ b/test/Setter.ts @@ -3,7 +3,7 @@ import * as assert from 'assert' type Point = { x: number; y: number } -const _x = new Setter((f: (a: number) => number, s: Point): Point => ({ +const _x = new Setter(f => s => ({ x: f(s.x), y: s.y })) @@ -13,12 +13,12 @@ describe('Setter', () => { const eg0 = { x: 42, y: -1 } it('modify', () => { - const eg1 = _x.modify(double, eg0) + const eg1 = _x.modify(double)(eg0) assert.strictEqual(eg1.x, double(eg0.x)) assert.strictEqual(eg1.y, eg0.y) }) it('set', () => { - assert.strictEqual(_x.set(0, eg0).x, 0) + assert.strictEqual(_x.set(0)(eg0).x, 0) }) }) diff --git a/test/conversions.ts b/test/conversions.ts index 2e86b78..050d849 100644 --- a/test/conversions.ts +++ b/test/conversions.ts @@ -8,7 +8,7 @@ type U1 = false const anIso = new Iso(() => false, () => true) -const hasType = (t: T): void => assert(true) +const hasType = (_: T): void => assert(true) describe('Conversions', () => { it('type check', () => {