import type { Either } from './Either' import type { FunctorMin } from './Functor' import type { Option } from './Option' import type { Predicate } from './Predicate' import type { Refinement } from './Refinement' import * as E from './Either' import { Functor } from './Functor' import * as HKT from './HKT' import * as O from './Option' export interface Filterable extends Functor { readonly partitionMap_: PartitionMapFn_ readonly partitionMap: PartitionMapFn readonly partition_: PartitionFn_ readonly partition: PartitionFn readonly filterMap_: FilterMapFn_ readonly filterMap: FilterMapFn readonly filter_: FilterFn_ readonly filter: FilterFn } export type FilterableMin = FunctorMin & ( | { readonly filterMap_: FilterMapFn_ readonly partitionMap_: PartitionMapFn_ } | { readonly filterMap_: FilterMapFn_ readonly partitionMap_: PartitionMapFn_ readonly filter_: FilterFn_ readonly partition_: PartitionFn_ } ) export function Filterable(F: FilterableMin): Filterable export function Filterable(F: FilterableMin>): Filterable> { const filterMap_: FilterMapFn_> = F.filterMap_ const partitionMap_: PartitionMapFn_> = F.partitionMap_ let partition_: PartitionFn_> let filter_: FilterFn_> if ('filter_' in F) { filter_ = F.filter_ } else { filter_ = (fa: HKT.HKT, predicate: Predicate): HKT.HKT => F.filterMap_(fa, (a) => O.fromPredicate_(a, predicate)) } if ('partition_' in F) { partition_ = F.partition_ } else { partition_ = (fa: HKT.HKT, predicate: Predicate): readonly [HKT.HKT, HKT.HKT] => partitionMap_(fa, (a) => (predicate(a) ? E.Right(a) : E.Left(a))) } return HKT.instance>>({ ...Functor(F), filterMap_, filterMap: (f) => (fa) => filterMap_(fa, f), partitionMap_, partitionMap: (f) => (fa) => partitionMap_(fa, f), filter_, filter: (f: Predicate) => (fa: HKT.HKT) => filter_(fa, f), partition_, partition: (f: Predicate) => (fa: HKT.HKT) => partition_(fa, f) }) } export interface FilterFn { (refinement: Refinement): ( fa: HKT.Kind ) => HKT.Kind (predicate: Predicate): ( fa: HKT.Kind ) => HKT.Kind } export interface FilterFn_ { ( fa: HKT.Kind, refinement: Refinement ): HKT.Kind ( fa: HKT.Kind, predicate: Predicate ): HKT.Kind } export interface FilterMapFn { (f: (a: A) => Option): ( fa: HKT.Kind ) => HKT.Kind } export interface FilterMapFn_ { ( fa: HKT.Kind, f: (a: A) => Option ): HKT.Kind } export interface PartitionFn { (refinement: Refinement): ( fa: HKT.Kind ) => readonly [HKT.Kind, HKT.Kind] (predicate: Predicate): ( fa: HKT.Kind ) => readonly [HKT.Kind, HKT.Kind] } export interface PartitionFn_ { ( fa: HKT.Kind, refinement: Refinement ): readonly [HKT.Kind, HKT.Kind] ( fa: HKT.Kind, predicate: Predicate ): readonly [HKT.Kind, HKT.Kind] } export interface PartitionMapFn { (f: (a: A) => Either): ( fa: HKT.Kind ) => readonly [HKT.Kind, HKT.Kind] } export interface PartitionMapFn_ { ( fa: HKT.Kind, f: (a: A) => Either ): readonly [HKT.Kind, HKT.Kind] }