import * as _Alt from 'fp-ts/Alt'
import * as Alte from 'fp-ts/Alternative'
import * as Appli from 'fp-ts/Applicative'
import * as _Apply from 'fp-ts/Apply'
import * as Ch from 'fp-ts/Chain'
import * as Co from 'fp-ts/Compactable'
import * as Ei from 'fp-ts/Either'
import * as Eq from 'fp-ts/Eq'
import * as Ex from 'fp-ts/Extend'
import * as Fi from 'fp-ts/Filterable'
import * as FiWI from 'fp-ts/FilterableWithIndex'
import * as Fo from 'fp-ts/Foldable'
import * as FoWI from 'fp-ts/FoldableWithIndex'
import * as FIO from 'fp-ts/FromIO'
import {
constFalse,
constTrue,
flip,
flow,
identity,
Lazy,
pipe,
} from 'fp-ts/function'
import * as Fu from 'fp-ts/Functor'
import * as FuWI from 'fp-ts/FunctorWithIndex'
import {
HKT,
Kind,
Kind2,
Kind3,
Kind4,
URIS,
URIS2,
URIS3,
URIS4,
} from 'fp-ts/HKT'
import * as IO from 'fp-ts/IO'
import * as Mona from 'fp-ts/Monad'
import * as MIO from 'fp-ts/MonadIO'
import * as Mono from 'fp-ts/Monoid'
import * as Op from 'fp-ts/Option'
import * as Or from 'fp-ts/Ord'
import * as P from 'fp-ts/Pointed'
import * as Pr from 'fp-ts/Predicate'
import * as R from 'fp-ts/Random'
import * as RA from 'fp-ts/ReadonlyArray'
import * as RNEA from 'fp-ts/ReadonlyNonEmptyArray'
import * as RR from 'fp-ts/ReadonlyRecord'
import * as Re from 'fp-ts/Refinement'
import * as S from 'fp-ts/Separated'
import * as T from 'fp-ts/Traversable'
import * as TWI from 'fp-ts/TraversableWithIndex'
import * as U from 'fp-ts/Unfoldable'
import * as W from 'fp-ts/Witherable'
import { Int } from 'io-ts'
import { curry } from './function'
export const URI = 'Yield'
export type URI = typeof URI
declare module 'fp-ts/HKT' {
interface URItoKind {
[URI]: Yield
}
}
export type Yield = Lazy>
export const getMonoid = (): Mono.Monoid> => ({
empty: fromReadonlyArray([]),
concat: (x, y) =>
function* () {
yield* x()
yield* y()
},
})
export const getEq = (E: Eq.Eq): Eq.Eq> =>
Eq.fromEquals((x, y) => {
const bs = y()
for (const a of x()) {
const b = bs.next()
if (b.done || !E.equals(a, b.value)) {
return false
}
}
return Boolean(bs.next().done)
})
export const getOrd = (O: Or.Ord): Or.Ord> =>
Or.fromCompare((first, second) => {
const bs = second()
for (const a of first()) {
const b = bs.next()
if (b.done) {
return 1
}
const ordering = O.compare(a, b.value)
if (0 !== ordering) {
return ordering
}
}
return !bs.next().done ? -1 : 0
})
export const Functor: Fu.Functor1 = {
URI,
map: (fa, f) =>
function* () {
for (const a of fa()) {
yield f(a)
}
},
}
export const map = curry(flip(Functor.map))
export const flap = Fu.flap(Functor)
export const bindTo = Fu.bindTo(Functor)
export const Pointed: P.Pointed1 = {
URI,
of: (a) =>
function* () {
yield a
},
}
export const of = Pointed.of
export const Do = Pointed.of({})
export const FunctorWithIndex: FuWI.FunctorWithIndex1 = {
...Functor,
mapWithIndex: (fa, f) =>
Functor.map(pipe(fa, zip(range(0))), ([a, i]) => f(i, a)),
}
export const mapWithIndex = curry(flip(FunctorWithIndex.mapWithIndex))
export const Apply: _Apply.Apply1 = {
...Functor,
ap: (fab, fa) => Chain.chain(fab, curry(Functor.map)(fa)),
}
export const ap = curry(flip(Apply.ap))
export const apFirst = _Apply.apFirst(Apply)
export const apSecond = _Apply.apSecond(Apply)
export const apS = _Apply.apS(Apply)
export const Applicative: Appli.Applicative1 = { ...Pointed, ...Apply }
export const Chain: Ch.Chain1 = {
...Apply,
chain: (fa, f) => flatten(Functor.map(fa, f)),
}
export const chain = curry(flip(Chain.chain))
export const chainFirst = Ch.chainFirst(Chain)
export const bind = Ch.bind(Chain)
export const chainWithIndex =
(f: (i: number, a: A) => Yield) =>
(fa: Yield): Yield =>
pipe(
fa,
zip(range(0)),
chain(([a, i]) => f(i, a)),
)
export const Monad: Mona.Monad1 = { ...Applicative, ...Chain }
export const FromIO: FIO.FromIO1 = {
URI,
fromIO: (fa) => pipe(range(0), map(fa)),
}
export const fromIO = FromIO.fromIO
export const fromIOK = FIO.fromIOK(FromIO)
export const chainIOK = FIO.chainIOK(FromIO, Chain)
export const chainFirstIOK = FIO.chainFirstIOK(FromIO, Chain)
export const MonadIO: MIO.MonadIO1 = { ...Monad, ...FromIO }
export const Unfoldable: U.Unfoldable1 = {
URI,
unfold: (b, f) =>
function* () {
for (
let _b = b, ab = f(_b);
Op.isSome(ab);
_b = ab.value[1], ab = f(_b)
) {
yield ab.value[0]
}
},
}
export const unfold = curry(flip(Unfoldable.unfold))
export const Alt: _Alt.Alt1 = {
...Functor,
alt: (fa: Yield, that: Lazy>) =>
getMonoid().concat(fa, that()),
}
export const alt = curry(flip(Alt.alt))
export const Alternative: Alte.Alternative1 = {
...Applicative,
...Alt,
zero: () => getMonoid().empty,
}
export const zero = Alternative.zero
export const Extend: Ex.Extend1 = {
...Functor,
extend: (wa, f) =>
pipe(
wa,
mapWithIndex((i) => pipe(wa, dropLeft(i), f)),
),
}
export const extend = curry(flip(Extend.extend))
export const duplicate = (fa: Yield) => pipe(fa, extend(identity))
export const Compactable: Co.Compactable1 = {
URI,
compact: (fa) =>
Functor.map(Filterable.filter(fa, Op.isSome), (a) => a.value),
separate: (fa) =>
S.separated(
Functor.map(Filterable.filter(fa, Ei.isLeft), (a) => a.left),
Functor.map(Filterable.filter(fa, Ei.isRight), (a) => a.right),
),
}
export const compact = Compactable.compact
export const separate = Compactable.separate
function _filter(
fa: Yield,
refinement: Re.Refinement,
): Yield
function _filter(fa: Yield, predicate: Pr.Predicate): Yield
function _filter(fa: Yield, predicate: Pr.Predicate) {
return function* () {
for (const a of fa()) {
if (!predicate(a)) {
continue
}
yield a
}
}
}
function _partition(
fa: Yield,
refinement: Re.Refinement,
): S.Separated, Yield>
function _partition(
fa: Yield,
predicate: Pr.Predicate,
): S.Separated, Yield>
function _partition(fa: Yield, predicate: Pr.Predicate) {
return S.separated(
Filterable.filter(fa, Pr.not(predicate)),
Filterable.filter(fa, predicate),
)
}
export const Filterable: Fi.Filterable1 = {
...Functor,
...Compactable,
filter: _filter,
filterMap: (fa, f) => Compactable.compact(Functor.map(fa, f)),
partition: _partition,
partitionMap: (fa, f) => Compactable.separate(Functor.map(fa, f)),
}
export function filter(
refinement: Re.Refinement,
): (fa: Yield) => Yield
export function filter(
predicate: Pr.Predicate,
): (fa: Yield) => Yield
export function filter(predicate: Pr.Predicate) {
return (fa: Yield) => Filterable.filter(fa, predicate)
}
export const filterMap = curry(flip(Filterable.filterMap))
export function partition(
refinement: Re.Refinement,
): (fa: Yield) => S.Separated, Yield>
export function partition(
predicate: Pr.Predicate,
): (fa: Yield) => S.Separated, Yield>
export function partition(predicate: Pr.Predicate) {
return (fa: Yield) => Filterable.partition(fa, predicate)
}
export const partitionMap = curry(flip(Filterable.partitionMap))
function _filterWithIndex(
fa: Yield,
refinementWithIndex: (i: number, a: A) => a is B,
): Yield
function _filterWithIndex(
fa: Yield,
predicateWithIndex: (i: number, a: A) => boolean,
): Yield
function _filterWithIndex(
fa: Yield,
predicateWithIndex: (i: number, a: A) => boolean,
) {
return Compactable.compact(
FunctorWithIndex.mapWithIndex(fa, (i, a) =>
predicateWithIndex(i, a) ? Op.some(a) : Op.none,
),
)
}
function _partitionWithIndex(
fa: Yield,
refinementWithIndex: (i: number, a: A) => a is B,
): S.Separated, Yield>
function _partitionWithIndex(
fa: Yield,
predicateWithIndex: (i: number, a: A) => boolean,
): S.Separated, Yield>
function _partitionWithIndex(
fa: Yield,
predicateWithIndex: (i: number, a: A) => boolean,
) {
return Compactable.separate(
FunctorWithIndex.mapWithIndex(fa, (i, a) =>
predicateWithIndex(i, a) ? Ei.right(a) : Ei.left(a),
),
)
}
export const FilterableWithIndex: FiWI.FilterableWithIndex1 = {
...FunctorWithIndex,
...Filterable,
filterWithIndex: _filterWithIndex,
filterMapWithIndex: (fa, f) =>
Compactable.compact(FunctorWithIndex.mapWithIndex(fa, f)),
partitionWithIndex: _partitionWithIndex,
partitionMapWithIndex: (fa, f) =>
Compactable.separate(FunctorWithIndex.mapWithIndex(fa, f)),
}
export function filterWithIndex(
refinementWithIndex: (i: number, a: A) => a is B,
): (fa: Yield) => Yield
export function filterWithIndex(
predicateWithIndex: (i: number, a: A) => boolean,
): (fa: Yield) => Yield
export function filterWithIndex(
predicateWithIndex: (i: number, a: A) => boolean,
) {
return (fa: Yield) =>
FilterableWithIndex.filterWithIndex(fa, predicateWithIndex)
}
export const filterMapWithIndex = curry(
flip(FilterableWithIndex.filterMapWithIndex),
)
export function partitionWithIndex(
refinementWithIndex: (i: number, a: A) => a is B,
): (fa: Yield) => S.Separated, Yield>
export function partitionWithIndex(
predicateWithIndex: (i: number, a: A) => boolean,
): (fa: Yield) => S.Separated, Yield>
export function partitionWithIndex(
predicateWithIndex: (i: number, a: A) => boolean,
) {
return (fa: Yield) =>
FilterableWithIndex.partitionWithIndex(fa, predicateWithIndex)
}
export const partitionMapWithIndex = curry(
flip(FilterableWithIndex.partitionMapWithIndex),
)
export const Foldable: Fo.Foldable1 = {
URI,
reduce: (fa, b, f) =>
FoldableWithIndex.reduceWithIndex(fa, b, (_, _b, a) => f(_b, a)),
foldMap: (M) => (fa, f) =>
FoldableWithIndex.foldMapWithIndex(M)(fa, (_, a) => f(a)),
reduceRight: (fa, b, f) =>
FoldableWithIndex.reduceRightWithIndex(fa, b, (_, a, _b) => f(a, _b)),
}
export const reduce =
(b: B, f: (b: B, a: A) => B) =>
(fa: Yield) =>
Foldable.reduce(fa, b, f)
export const foldMap =
(M: Mono.Monoid) =>
(f: (a: A) => M) =>
(fa: Yield) =>
Foldable.foldMap(M)(fa, f)
export const reduceRight =
(b: B, f: (a: A, b: B) => B) =>
(fa: Yield) =>
Foldable.reduceRight(fa, b, f)
export const FoldableWithIndex: FoWI.FoldableWithIndex1 = {
...Foldable,
reduceWithIndex: (fa, b, f) =>
pipe(fa, zip(range(0)), (_fa) => {
let _b = b
for (const [a, i] of _fa()) {
_b = f(i, _b, a)
}
return _b
}),
foldMapWithIndex: (M) => (fa, f) =>
FoldableWithIndex.reduceWithIndex(fa, M.empty, (i, b, a) =>
M.concat(b, f(i, a)),
),
reduceRightWithIndex: (fa, b, f) =>
pipe(fa, toReadonlyArray, RA.reduceRightWithIndex(b, f)),
}
export const reduceWithIndex =
(b: B, f: (i: number, b: B, a: A) => B) =>
(fa: Yield) =>
FoldableWithIndex.reduceWithIndex(fa, b, f)
export const foldMapWithIndex =
(M: Mono.Monoid) =>
(f: (i: number, a: A) => M) =>
(fa: Yield) =>
FoldableWithIndex.foldMapWithIndex(M)(fa, f)
export const reduceRightWithIndex =
(b: B, f: (i: number, a: A, b: B) => B) =>
(fa: Yield) =>
FoldableWithIndex.reduceRightWithIndex(fa, b, f)
function _traverse(
F: Appli.Applicative4,
): (
ta: Yield,
f: (a: A) => Kind4,
) => Kind4>
function _traverse(
F: Appli.Applicative3,
): (
ta: Yield,
f: (a: A) => Kind3,
) => Kind3>
function _traverse(
F: Appli.Applicative3C,
): (
ta: Yield,
f: (a: A) => Kind3,
) => Kind3>
function _traverse(
F: Appli.Applicative2,
): (ta: Yield, f: (a: A) => Kind2) => Kind2>
function _traverse(
F: Appli.Applicative2C,
): (ta: Yield, f: (a: A) => Kind2) => Kind2>
function _traverse(
F: Appli.Applicative1,
): (ta: Yield, f: (a: A) => Kind) => Kind>
function _traverse(F: Appli.Applicative) {
return (ta: Yield, f: (a: A) => HKT) =>
TraversableWithIndex.traverseWithIndex(F)(ta, (_: number, a: A) => f(a))
}
export function sequence(
F: Appli.Applicative4,
): (ta: Yield>) => Kind4>
export function sequence(
F: Appli.Applicative3,
): (ta: Yield>) => Kind3>
export function sequence(
F: Appli.Applicative3C,
): (ta: Yield>) => Kind3>
export function sequence(
F: Appli.Applicative2,
): (ta: Yield>) => Kind2>
export function sequence(
F: Appli.Applicative2C,
): (ta: Yield>) => Kind2>
export function sequence(
F: Appli.Applicative1,
): (ta: Yield>) => Kind>
export function sequence(
F: Appli.Applicative,
): (ta: Yield>) => HKT> {
return (ta: Yield>) => Traversable.traverse(F)(ta, identity)
}
export const Traversable: T.Traversable1 = {
...Functor,
...Foldable,
traverse: _traverse,
sequence,
}
export function traverse(
F: Appli.Applicative4,
): (
f: (a: A) => Kind4,
) => (ta: Yield) => Kind4>
export function traverse(
F: Appli.Applicative3,
): (
f: (a: A) => Kind3,
) => (ta: Yield) => Kind3>
export function traverse(
F: Appli.Applicative3C,
): (
f: (a: A) => Kind3,
) => (ta: Yield) => Kind3>
export function traverse(
F: Appli.Applicative2,
): (
f: (a: A) => Kind2,
) => (ta: Yield) => Kind2>
export function traverse(
F: Appli.Applicative2C,
): (
f: (a: A) => Kind2,
) => (ta: Yield) => Kind2>
export function traverse(
F: Appli.Applicative1,
): (f: (a: A) => Kind) => (ta: Yield) => Kind>
export function traverse(F: Appli.Applicative) {
return (f: (a: A) => HKT) =>
(ta: Yield) =>
Traversable.traverse(F)(ta, f)
}
function _traverseWithIndex(
F: Appli.Applicative4,
): (
ta: Yield,
f: (i: number, a: A) => Kind4,
) => Kind4>
function _traverseWithIndex(
F: Appli.Applicative3,
): (
ta: Yield,
f: (i: number, a: A) => Kind3,
) => Kind3>
function _traverseWithIndex(
F: Appli.Applicative3C,
): (
ta: Yield,
f: (i: number, a: A) => Kind3,
) => Kind3>
function _traverseWithIndex(
F: Appli.Applicative2,
): (
ta: Yield,
f: (i: number, a: A) => Kind2,
) => Kind2>
function _traverseWithIndex(
F: Appli.Applicative2C,
): (
ta: Yield,
f: (i: number, a: A) => Kind2,
) => Kind2>
function _traverseWithIndex(
F: Appli.Applicative1,
): (ta: Yield, f: (i: number, a: A) => Kind) => Kind>
function _traverseWithIndex(F: Appli.Applicative) {
return (ta: Yield, f: (i: number, a: A) => HKT) =>
FoldableWithIndex.reduceWithIndex(ta, F.of(zero()), (i, fbs, a) =>
F.ap(
F.map(fbs, (bs) => (b: B) => pipe(bs, append(b))),
f(i, a),
),
)
}
export const TraversableWithIndex: TWI.TraversableWithIndex1 = {
...FunctorWithIndex,
...FoldableWithIndex,
...Traversable,
traverseWithIndex: _traverseWithIndex,
}
export function traverseWithIndex(
F: Appli.Applicative4,
): (
f: (i: number, a: A) => Kind4,
) => (ta: Yield) => Kind4>
export function traverseWithIndex(
F: Appli.Applicative3,
): (
f: (i: number, a: A) => Kind3,
) => (ta: Yield) => Kind3>
export function traverseWithIndex(
F: Appli.Applicative3C,
): (
f: (i: number, a: A) => Kind3,
) => (ta: Yield) => Kind3>
export function traverseWithIndex(
F: Appli.Applicative2,
): (
f: (i: number, a: A) => Kind2,
) => (ta: Yield) => Kind2>
export function traverseWithIndex(
F: Appli.Applicative2C,
): (
f: (i: number, a: A) => Kind2,
) => (ta: Yield) => Kind2>
export function traverseWithIndex(
F: Appli.Applicative1