Skip to content

Commit

Permalink
compatibility with TypeScript 2.6.x (strictFunctionType = true), fix #…
Browse files Browse the repository at this point in the history
  • Loading branch information
gcanti committed Oct 18, 2017
1 parent 63c431f commit 2a56114
Show file tree
Hide file tree
Showing 66 changed files with 546 additions and 842 deletions.
2 changes: 1 addition & 1 deletion docs/fantas-eel-and-specification/10.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ import { Plus } from '../../src/Plus'
import { Monoid } from '../../src/Monoid'

export const getMonoid = <F>(plus: Plus<F>) => <A>(): Monoid<HKT<F, A>> => ({
concat: plus.alt,
concat: x => y => plus.alt(x, y),
empty: plus.zero
})
10 changes: 6 additions & 4 deletions docs/fantas-eel-and-specification/13.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,23 +57,23 @@ export const sqrt = (x: number): either.Either<string, number> =>

console.log(
either
.right(16)
.right<string, number>(16)
.chain(sqrt)
.chain(sqrt)
)
// => right(2)

console.log(
either
.right(81)
.right<string, number>(81)
.chain(sqrt)
.map(x => -x)
.chain(sqrt)
.map(x => -x)
)
// => left("Hey, no!")

console.log(either.left('eep').chain(sqrt))
console.log(either.left<string, number>('eep').chain(sqrt))
// => left("eep")

//
Expand All @@ -90,7 +90,9 @@ const flights = {
JFK: ['LAX', 'DEN']
}

const whereNext = (x: keyof typeof flights): Array<string> => flights[x] || []
type FLIGHT = keyof typeof flights

const whereNext = (x: FLIGHT): Array<FLIGHT> => (flights[x] || []) as Array<FLIGHT>

console.log(array.chain(whereNext, array.chain(whereNext, whereNext('LAX'))))
// => [ 'JFK', 'ATL', 'ATL', 'ORD', 'DFW', 'JFK', 'ATL' ]
Expand Down
2 changes: 1 addition & 1 deletion docs/fantas-eel-and-specification/17.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export const isSurvivor = (game: Game): boolean => {
export const fromBoard = (board: Board): Game => {
return new Store(pointer => {
const [x, y] = pointer.value
return getBoardValue(board, x, y).getOrElse(() => false)
return getBoardValue(board, x, y).getOrElseValue(false)
}, new Tuple([0, 0]))
}

Expand Down
4 changes: 3 additions & 1 deletion docs/fantas-eel-and-specification/18.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ export class Costar<F, B, C> {
import * as array from '../../src/Array'

// Takes a list of ints to the sum
export const sum = new Costar<'Array', number, number>(array, (xs: Array<number>) => xs.reduce((acc, x) => acc + x, 0))
export const sum = new Costar<'Array', number, number>(array, (xs: HKT<'Array', number>) =>
(xs as Array<number>).reduce((acc, x) => acc + x, 0)
)

// Make every element 1, then sum them!
export const length = sum.promap<any, number>(() => 1, x => x)
Expand Down
6 changes: 3 additions & 3 deletions docs/fantas-eel-and-specification/8.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ console.log(option.none.ap(option.none)) // => none
import * as either from '../../src/Either'

console.log(either.right(2).ap(either.right((x: number) => -x))) // => right(-2)
console.log(either.left('halp').ap(either.right((x: number) => -x))) // => left("halp")
console.log(either.right(2).ap(either.left('eek'))) // => left("eek")
console.log(either.left('halp').ap(either.left('eek'))) // => left("eek")
console.log(either.left<string, number>('halp').ap(either.right((x: number) => -x))) // => left("halp")
console.log(either.right<string, number>(2).ap(either.left<string, (x: number) => number>('eek'))) // => left("eek")
console.log(either.left<string, number>('halp').ap(either.left<string, (x: number) => number>('eek'))) // => left("eek")

//
// Task
Expand Down
14 changes: 9 additions & 5 deletions docs/fantas-eel-and-specification/9.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ export const append = <A>(y: A) => (xs: Array<A>) => xs.concat([y])
export function insideOut<F extends HKTS>(F: Applicative<F>): <A>(xs: Array<HKTAs<F, A>>) => HKTAs<F, Array<A>>
export function insideOut<F>(F: Applicative<F>): <A>(xs: Array<HKT<F, A>>) => HKT<F, Array<A>>
export function insideOut<F>(F: Applicative<F>): <A>(xs: Array<HKT<F, A>>) => HKT<F, Array<A>> {
return <A>(xs: Array<HKT<F, A>>) => xs.reduce((acc, x) => liftA2(F)<A, Array<A>, Array<A>>(append)(x)(acc), F.of([]))
return <A>(xs: Array<HKT<F, A>>) =>
xs.reduce((acc, x) => liftA2(F)<A, Array<A>, Array<A>>(append)(x)(acc), F.of<A[]>([]))
}

import * as option from '../../src/Option'
Expand All @@ -37,10 +38,13 @@ import { getArrayMonoid } from '../../src/Monoid'
const monoidArrayNumber = getArrayMonoid<number>()

// Usual implementation:
console.log(option.concat(monoidArrayNumber)(option.some([2]))(option.some([3]))) // => some([2, 3])
console.log(option.concat(monoidArrayNumber)(option.some([2]))(option.none)) // => some([2])
console.log(option.concat(monoidArrayNumber)(option.none)(option.some([3]))) // => some([3])
console.log(option.concat(monoidArrayNumber)(option.none)(option.none)) // => none

const { concat } = option.getSemigroup(monoidArrayNumber)

console.log(concat(option.some([2]))(option.some([3]))) // => some([2, 3])
console.log(concat(option.some([2]))(option.none)) // => some([2])
console.log(concat(option.none)(option.some([3]))) // => some([3])
console.log(concat(option.none)(option.none)) // => none

// With the above implementation

Expand Down
4 changes: 2 additions & 2 deletions examples/ArrayOption.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ export class ArrayOption<A> implements FantasyMonad<URI, A> {
chain<B>(f: (a: A) => ArrayOption<B>): ArrayOption<B> {
return new ArrayOption(optionTArray.chain(a => f(a).value, this.value))
}
getOrElse(f: Lazy<A>): Array<A> {
return optionT.getOrElse(array)(f)(this.value)
getOrElseValue(a: A): Array<A> {
return optionT.getOrElseValue(array)(a)(this.value)
}
fold<R>(none: Lazy<R>, some: (a: A) => R): Array<R> {
return optionT.fold(array)(none, some, this.value)
Expand Down
4 changes: 2 additions & 2 deletions examples/EitherOption.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ export class EitherOption<L, A> implements FantasyMonad<URI, A> {
chain<B>(f: (a: A) => EitherOption<L, B>): EitherOption<L, B> {
return new EitherOption(optionTEither.chain(a => f(a).value, this.value))
}
getOrElse(f: Lazy<A>): either.Either<L, A> {
return optionT.getOrElse(either)(f)(this.value)
getOrElseValue(a: A): either.Either<L, A> {
return optionT.getOrElseValue(either)(a)(this.value)
}
fold<R>(none: Lazy<R>, some: (a: A) => R): either.Either<L, R> {
return optionT.fold(either)(none, some, this.value)
Expand Down
3 changes: 1 addition & 2 deletions examples/Moore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,7 @@ export const extract = <L, A>(fa: Moore<L, A>): A => fa.extract()

export const extend = <L, A, B>(f: (fa: Moore<L, A>) => B, fa: Moore<L, A>): Moore<L, B> => fa.extend(f)

export const promap = <A, B, C, D>(f: (a: A) => B, g: (c: C) => D) => (fla: Moore<B, C>): Moore<A, D> =>
fla.promap(f, g)
export const promap = <A, B, C, D>(f: (a: A) => B, g: (c: C) => D, fla: Moore<B, C>): Moore<A, D> => fla.promap(f, g)

/** Construct a Moore machine from a state valuation and transition function */
export const unfoldMoore = <S, L, A>(f: (s: S) => [A, (l: L) => S]) => (s: S): Moore<L, A> => {
Expand Down
10 changes: 6 additions & 4 deletions examples/ReaderIO.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,21 @@ export class ReaderIO<E, A> implements FantasyMonad<URI, A> {
readonly _A: A
readonly _L: E
readonly _URI: URI
constructor(readonly value: (e: E) => io.IO<A>) {}
constructor(readonly run: (e: E) => io.IO<A>) {}
map<B>(f: (a: A) => B): ReaderIO<E, B> {
return new ReaderIO(readerTIO.map(f, this.value))
return new ReaderIO(readerTIO.map(f, this.run))
}
of<E, B>(b: B): ReaderIO<E, B> {
return of(b)
}
ap<B>(fab: ReaderIO<E, (a: A) => B>): ReaderIO<E, B> {
return new ReaderIO(readerTIO.ap(fab.value, this.value))
return new ReaderIO(readerTIO.ap(fab.run, this.run))
}
ap_<B, C>(this: ReaderIO<E, (a: B) => C>, fb: ReaderIO<E, B>): ReaderIO<E, C> {
return fb.ap(this)
}
chain<B>(f: (a: A) => ReaderIO<E, B>): ReaderIO<E, B> {
return new ReaderIO(readerTIO.chain(a => f(a).value, this.value))
return new ReaderIO(readerTIO.chain(a => f(a).run, this.run))
}
}

Expand All @@ -48,6 +48,8 @@ export const ask = <E>(e: E): ReaderIO<E, E> => new ReaderIO(readerT.ask(io)())

export const asks = <E, A>(f: (e: E) => A): ReaderIO<E, A> => new ReaderIO(readerT.asks(io)(f))

export const local = <E>(f: (e: E) => E) => <A>(fa: ReaderIO<E, A>): ReaderIO<E, A> => new ReaderIO(e => fa.run(f(e)))

export const readerIO: Monad<URI> = {
URI,
map,
Expand Down
82 changes: 82 additions & 0 deletions examples/ReaderTaskEither.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import * as readerT from 'fp-ts/lib/ReaderT'
import * as taskEither from 'fp-ts/lib/TaskEither'
import { TaskEither } from 'fp-ts/lib/TaskEither'
import { Monad, FantasyMonad } from 'fp-ts/lib/Monad'
import { Task } from 'fp-ts/lib/Task'
import { Either } from 'fp-ts/lib/Either'

const readerTTaskEither = readerT.getReaderT(taskEither)

declare module 'fp-ts/lib/HKT' {
interface URI2HKT3<U, L, A> {
ReaderTaskEither: ReaderTaskEither<U, L, A>
}
}

export const URI = 'ReaderTaskEither'

export type URI = typeof URI

export class ReaderTaskEither<E, L, A> implements FantasyMonad<URI, A> {
readonly _A: A
readonly _L: L
readonly _U: E
readonly _URI: URI
constructor(readonly run: (e: E) => TaskEither<L, A>) {}
map<B>(f: (a: A) => B): ReaderTaskEither<E, L, B> {
return new ReaderTaskEither(readerTTaskEither.map(f, this.run))
}
of<E, B>(b: B): ReaderTaskEither<E, L, B> {
return of(b)
}
ap<B>(fab: ReaderTaskEither<E, L, (a: A) => B>): ReaderTaskEither<E, L, B> {
return new ReaderTaskEither(readerTTaskEither.ap(fab.run, this.run))
}
ap_<B, C>(this: ReaderTaskEither<E, L, (a: B) => C>, fb: ReaderTaskEither<E, L, B>): ReaderTaskEither<E, L, C> {
return fb.ap(this)
}
chain<B>(f: (a: A) => ReaderTaskEither<E, L, B>): ReaderTaskEither<E, L, B> {
return new ReaderTaskEither(readerTTaskEither.chain(a => f(a).run, this.run))
}
}

export const map = <E, L, A, B>(f: (a: A) => B, fa: ReaderTaskEither<E, L, A>): ReaderTaskEither<E, L, B> => fa.map(f)

export const of = <E, L, A>(a: A): ReaderTaskEither<E, L, A> => new ReaderTaskEither(readerTTaskEither.of(a))

export const ap = <E, L, A, B>(
fab: ReaderTaskEither<E, L, (a: A) => B>,
fa: ReaderTaskEither<E, L, A>
): ReaderTaskEither<E, L, B> => fa.ap(fab)

export const chain = <E, L, A, B>(
f: (a: A) => ReaderTaskEither<E, L, B>,
fa: ReaderTaskEither<E, L, A>
): ReaderTaskEither<E, L, B> => fa.chain(f)

export const ask = <E, L>(e: E): ReaderTaskEither<E, L, E> => new ReaderTaskEither(readerT.ask(taskEither)())

export const asks = <E, L, A>(f: (e: E) => A): ReaderTaskEither<E, L, A> =>
new ReaderTaskEither(readerT.asks(taskEither)(f))

export const local = <E>(f: (e: E) => E) => <L, A>(fa: ReaderTaskEither<E, L, A>): ReaderTaskEither<E, L, A> =>
new ReaderTaskEither(e => fa.run(f(e)))

export const right = <E, L, A>(fa: Task<A>): ReaderTaskEither<E, L, A> =>
new ReaderTaskEither(() => taskEither.right(fa))

export const left = <E, L, A>(fa: Task<L>): ReaderTaskEither<E, L, A> => new ReaderTaskEither(() => taskEither.left(fa))

export const fromEither = <E, L, A>(fa: Either<L, A>): ReaderTaskEither<E, L, A> =>
new ReaderTaskEither(() => taskEither.fromEither(fa))

export const tryCatch = <E, L, A>(f: (e: E) => Promise<A>, onrejected: (reason: {}) => L): ReaderTaskEither<E, L, A> =>
new ReaderTaskEither(e => taskEither.tryCatch(() => f(e), onrejected))

export const readerTaskEither: Monad<URI> = {
URI,
map,
of,
ap,
chain
}
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "fp-ts",
"version": "0.5.4",
"version": "0.6.0-dev.20171016",
"description": "Functional programming in TypeScript",
"files": ["lib"],
"main": "lib/index.js",
Expand Down Expand Up @@ -36,7 +36,7 @@
"ts-node": "3.1.0",
"tslint": "4.4.2",
"tslint-config-standard": "4.0.0",
"typescript": "^2.5.2"
"typescript": "2.6.0-rc"
},
"tags": ["typescript", "static-land", "fantasy-land", "algebraic-data-types", "functional-programming"],
"keywords": ["typescript", "static-land", "fantasy-land", "algebraic-data-types", "functional-programming"]
Expand Down
4 changes: 2 additions & 2 deletions src/Alt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import { HKT } from './HKT'
import { Functor, FantasyFunctor } from './Functor'

export interface Alt<F> extends Functor<F> {
alt: <A>(fx: HKT<F, A>) => (fy: HKT<F, A>) => HKT<F, A>
alt<A>(fx: HKT<F, A>, fy: HKT<F, A>): HKT<F, A>
}

export interface FantasyAlt<F, A> extends FantasyFunctor<F, A> {
alt: (fy: HKT<F, A>) => HKT<F, A>
alt(fy: HKT<F, A>): HKT<F, A>
}
27 changes: 15 additions & 12 deletions src/Applicative.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { HKT, HKTS, HKT2S, HKTAs, HKT2As } from './HKT'
import { HKT, HKTS, HKT2S, HKTAs, HKT2As, HKT3S, HKT3As } from './HKT'
import { Apply, FantasyApply } from './Apply'
import {
getFunctorComposition,
Expand All @@ -17,39 +17,42 @@ export interface FantasyApplicative<F, A> extends FantasyApply<F, A> {}

export interface ApplicativeComposition<F, G> extends FunctorComposition<F, G> {
of: <A>(a: A) => HKT<F, HKT<G, A>>
ap: <A, B>(fgab: HKT<F, HKT<G, (a: A) => B>>, fga: HKT<F, HKT<G, A>>) => HKT<F, HKT<G, B>>
ap<A, B>(fgab: HKT<F, HKT<G, (a: A) => B>>, fga: HKT<F, HKT<G, A>>): HKT<F, HKT<G, B>>
}

export interface ApplicativeComposition11<F extends HKTS, G extends HKTS> extends FunctorComposition11<F, G> {
of: <A>(a: A) => HKTAs<F, HKTAs<G, A>>
ap: <A, B>(fgab: HKTAs<F, HKTAs<G, (a: A) => B>>, fga: HKTAs<F, HKTAs<G, A>>) => HKTAs<F, HKTAs<G, B>>
ap<A, B>(fgab: HKTAs<F, HKTAs<G, (a: A) => B>>, fga: HKTAs<F, HKTAs<G, A>>): HKTAs<F, HKTAs<G, B>>
}

export interface ApplicativeComposition12<F extends HKTS, G extends HKT2S> extends FunctorComposition12<F, G> {
of: <L, A>(a: A) => HKTAs<F, HKT2As<G, L, A>>
ap: <L, A, B>(fgab: HKTAs<F, HKT2As<G, L, (a: A) => B>>, fga: HKTAs<F, HKT2As<G, L, A>>) => HKTAs<F, HKT2As<G, L, B>>
ap<L, A, B>(fgab: HKTAs<F, HKT2As<G, L, (a: A) => B>>, fga: HKTAs<F, HKT2As<G, L, A>>): HKTAs<F, HKT2As<G, L, B>>
}

export interface ApplicativeComposition21<F extends HKT2S, G extends HKTS> extends FunctorComposition21<F, G> {
of: <L, A>(a: A) => HKT2As<F, L, HKTAs<G, A>>
ap: <L, A, B>(fgab: HKT2As<F, L, HKTAs<G, (a: A) => B>>, fga: HKT2As<F, L, HKTAs<G, A>>) => HKT2As<F, L, HKTAs<G, B>>
ap<L, A, B>(fgab: HKT2As<F, L, HKTAs<G, (a: A) => B>>, fga: HKT2As<F, L, HKTAs<G, A>>): HKT2As<F, L, HKTAs<G, B>>
}

export interface ApplicativeComposition22<F extends HKT2S, G extends HKT2S> extends FunctorComposition22<F, G> {
of: <L, M, A>(a: A) => HKT2As<F, L, HKT2As<G, M, A>>
ap: <L, M, A, B>(
ap<L, M, A, B>(
fgab: HKT2As<F, L, HKT2As<G, M, (a: A) => B>>,
fga: HKT2As<F, L, HKT2As<G, M, A>>
) => HKT2As<F, L, HKT2As<G, M, B>>
): HKT2As<F, L, HKT2As<G, M, B>>
}

export class Ops {
/** Perform a applicative action when a condition is true */
when<F extends HKT2S>(F: Applicative<F>): (condition: boolean) => <L>(fu: HKT2As<F, L, void>) => HKT2As<F, L, void>
when<F extends HKTS>(F: Applicative<F>): (condition: boolean) => (fu: HKTAs<F, void>) => HKTAs<F, void>
when<F>(F: Applicative<F>): (condition: boolean) => (fu: HKT<F, void>) => HKT<F, void>
when<F>(F: Applicative<F>): (condition: boolean) => (fu: HKT<F, void>) => HKT<F, void> {
return condition => fu => (condition ? fu : F.of(undefined))
when<F extends HKT3S>(
F: Applicative<F>
): <U, L>(condition: boolean, fu: HKT3As<F, U, L, void>) => HKT3As<F, U, L, void>
when<F extends HKT2S>(F: Applicative<F>): <L>(condition: boolean, fu: HKT2As<F, L, void>) => HKT2As<F, L, void>
when<F extends HKTS>(F: Applicative<F>): (condition: boolean, fu: HKTAs<F, void>) => HKTAs<F, void>
when<F>(F: Applicative<F>): (condition: boolean, fu: HKT<F, void>) => HKT<F, void>
when<F>(F: Applicative<F>): (condition: boolean, fu: HKT<F, void>) => HKT<F, void> {
return (condition, fu) => (condition ? fu : F.of(undefined))
}

getApplicativeComposition<F extends HKT2S, G extends HKT2S>(
Expand Down
Loading

0 comments on commit 2a56114

Please sign in to comment.