Skip to content

Commit

Permalink
make Decoder module more tree shaking friendly and remove applicative…
Browse files Browse the repository at this point in the history
… instance
  • Loading branch information
gcanti committed May 21, 2020
1 parent 73d92a0 commit 4a6543b
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 114 deletions.
44 changes: 0 additions & 44 deletions docs/modules/Decoder.ts.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,6 @@ Added in v2.2.0
- [UnknownRecord](#unknownrecord)
- [alt](#alt)
- [altDecoder](#altdecoder)
- [alternativeDecoder](#alternativedecoder)
- [ap](#ap)
- [applicativeDecoder](#applicativedecoder)
- [applyDecoder](#applydecoder)
- [array](#array)
- [boolean](#boolean)
- [failure](#failure)
Expand Down Expand Up @@ -147,46 +143,6 @@ export declare const altDecoder: Alt1<'io-ts/Decoder'>
Added in v2.2.3
# alternativeDecoder
**Signature**
```ts
export declare const alternativeDecoder: Alternative1<'io-ts/Decoder'>
```
Added in v2.2.3
# ap
**Signature**
```ts
export declare const ap: <A>(fa: Decoder<A>) => <B>(fab: Decoder<(a: A) => B>) => Decoder<B>
```
Added in v2.2.0
# applicativeDecoder
**Signature**
```ts
export declare const applicativeDecoder: Applicative1<'io-ts/Decoder'>
```
Added in v2.2.3
# applyDecoder
**Signature**
```ts
export declare const applyDecoder: Apply1<'io-ts/Decoder'>
```
Added in v2.2.3
# array
**Signature**
Expand Down
67 changes: 17 additions & 50 deletions src/Decoder.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
/**
* @since 2.2.0
*/
import { Alternative1 } from 'fp-ts/lib/Alternative'
import { Applicative1 } from 'fp-ts/lib/Applicative'
import { Either, either, isLeft, isRight, left, mapLeft, right } from 'fp-ts/lib/Either'
import { Either, isLeft, isRight, left, mapLeft, right } from 'fp-ts/lib/Either'
import { NonEmptyArray } from 'fp-ts/lib/NonEmptyArray'
import { pipe } from 'fp-ts/lib/pipeable'
import { Forest, Tree } from 'fp-ts/lib/Tree'
import * as G from './Guard'
import { Literal, memoize, Schemable1, WithRefinement1, WithUnion1, WithUnknownContainers1 } from './Schemable'
import { Functor1 } from 'fp-ts/lib/Functor'
import { Alt1 } from 'fp-ts/lib/Alt'
import { Apply1 } from 'fp-ts/lib/Apply'

// -------------------------------------------------------------------------------------
// model
Expand All @@ -34,6 +31,10 @@ export interface Decoder<A> {
*/
export type TypeOf<D> = D extends Decoder<infer A> ? A : never

// -------------------------------------------------------------------------------------
// DecodeError
// -------------------------------------------------------------------------------------

const empty: Array<never> = []

/**
Expand Down Expand Up @@ -463,28 +464,25 @@ export function union<A extends ReadonlyArray<unknown>>(
/**
* @since 2.2.0
*/
export const alt: <A>(that: () => Decoder<A>) => (fa: Decoder<A>) => Decoder<A> = (that) => (fa) => alt_(fa, that)

const alt_: <A>(fx: Decoder<A>, fy: () => Decoder<A>) => Decoder<A> = (fx, fy) => ({
decode: (u) => either.alt(fx.decode(u), () => fy().decode(u))
})

/**
* @since 2.2.0
*/
export const ap: <A>(fa: Decoder<A>) => <B>(fab: Decoder<(a: A) => B>) => Decoder<B> = (fa) => (fab) => ap_(fab, fa)
export const map: <A, B>(f: (a: A) => B) => (fa: Decoder<A>) => Decoder<B> = (f) => (fa) => map_(fa, f)

const ap_: <A, B>(fab: Decoder<(a: A) => B>, fa: Decoder<A>) => Decoder<B> = (fab, fa) => ({
decode: (u) => either.ap(fab.decode(u), fa.decode(u))
const map_: <A, B>(fa: Decoder<A>, f: (a: A) => B) => Decoder<B> = (fa, f) => ({
decode: (u) => {
const e = fa.decode(u)
return isLeft(e) ? e : right(f(e.right))
}
})

/**
* @since 2.2.0
*/
export const map: <A, B>(f: (a: A) => B) => (fa: Decoder<A>) => Decoder<B> = (f) => (fa) => map_(fa, f)
export const alt: <A>(that: () => Decoder<A>) => (fa: Decoder<A>) => Decoder<A> = (that) => (fa) => alt_(fa, that)

const map_: <A, B>(fa: Decoder<A>, f: (a: A) => B) => Decoder<B> = (fa, f) => ({
decode: (u) => either.map(fa.decode(u), f)
const alt_: <A>(fx: Decoder<A>, fy: () => Decoder<A>) => Decoder<A> = (fx, fy) => ({
decode: (u) => {
const e = fx.decode(u)
return isLeft(e) ? fy().decode(u) : e
}
})

// -------------------------------------------------------------------------------------
Expand Down Expand Up @@ -515,25 +513,6 @@ export const functorDecoder: Functor1<URI> = {
map: map_
}

/**
* @since 2.2.3
*/
export const applyDecoder: Apply1<URI> = {
URI,
map: map_,
ap: ap_
}

/**
* @since 2.2.3
*/
export const applicativeDecoder: Applicative1<URI> = {
URI,
map: map_,
of,
ap: ap_
}

/**
* @since 2.2.3
*/
Expand All @@ -543,18 +522,6 @@ export const altDecoder: Alt1<URI> = {
alt: alt_
}

/**
* @since 2.2.3
*/
export const alternativeDecoder: Alternative1<URI> = {
URI,
map: map_,
of,
ap: ap_,
alt: alt_,
zero: () => never
}

/**
* @since 2.2.3
*/
Expand Down
2 changes: 1 addition & 1 deletion test/Codec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const undefinedGuard: G.Guard<undefined> = {
const undef: C.Codec<undefined, undefined> = C.fromDecoder(D.fromGuard(undefinedGuard, 'undefined'))

describe('Codec', () => {
describe('codec', () => {
describe('invariantCodec', () => {
it('imap', () => {
const codec = C.invariantCodec.imap(
C.string,
Expand Down
27 changes: 9 additions & 18 deletions test/Decoder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,23 @@ import { pipe } from 'fp-ts/lib/pipeable'
import * as D from '../src/Decoder'

describe('Decoder', () => {
describe('decoder', () => {
it('of', () => {
const decoder = D.of(1)
assert.deepStrictEqual(decoder.decode('aaa'), E.right(1))
})

describe('functorDecoder', () => {
it('map', () => {
const decoder = pipe(
D.string,
D.map((s) => s.length)
)
assert.deepStrictEqual(decoder.decode(null), E.left([D.tree('cannot decode null, should be string')]))
assert.deepStrictEqual(decoder.decode('aaa'), E.right(3))
})
})

it('of', () => {
const decoder = D.applicativeDecoder.of(1)
assert.deepStrictEqual(decoder.decode(1), E.right(1))
assert.deepStrictEqual(decoder.decode('a'), E.right(1))
})

it('ap', () => {
const fab = D.applicativeDecoder.of((s: string): number => s.length)
const fa = D.string
assert.deepStrictEqual(pipe(fab, D.ap(fa)).decode('aaa'), E.right(3))
})

describe('altDecoder', () => {
it('alt', () => {
const decoder = pipe(
D.string,
Expand All @@ -33,11 +29,6 @@ describe('Decoder', () => {
assert.deepStrictEqual(decoder.decode('a'), E.right('a'))
assert.deepStrictEqual(decoder.decode(1), E.right('1'))
})

it('zero', () => {
const decoder = D.alternativeDecoder.zero()
assert.deepStrictEqual(decoder.decode(null), E.left([D.tree('cannot decode null, should be never')]))
})
})

describe('union', () => {
Expand Down
2 changes: 1 addition & 1 deletion test/JsonEncoder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as assert from 'assert'
import * as JE from '../src/JsonEncoder'

describe('Encoder', () => {
describe('JsonEncoder', () => {
describe('contravariantJsonEncoder', () => {
it('contramap', () => {
const encoder = JE.contravariantJsonEncoder.contramap(JE.schemableJsonEncoder.number, (s: string) => s.length)
assert.deepStrictEqual(encoder.encode('aaa'), 3)
Expand Down

0 comments on commit 4a6543b

Please sign in to comment.