Skip to content

Instantly share code, notes, and snippets.

@baetheus
Created August 30, 2021 17:57
Show Gist options
  • Select an option

  • Save baetheus/9bfa19654200ee68dad5c4d8238444e5 to your computer and use it in GitHub Desktop.

Select an option

Save baetheus/9bfa19654200ee68dad5c4d8238444e5 to your computer and use it in GitHub Desktop.
Playing with Iterable/AsyncIterable
import type * as HKT from "./hkt.ts";
import type * as TC from "./type_classes.ts";
import { createDo } from "./derivations.ts";
import { createSequenceStruct, createSequenceTuple } from "./sequence.ts";
/*******************************************************************************
* Kind Registration
******************************************************************************/
export const URI = "Iterable";
export type URI = typeof URI;
declare module "./hkt.ts" {
// deno-lint-ignore no-explicit-any
export interface Kinds<_ extends any[]> {
[URI]: Iterable<_[0]>;
}
}
/*******************************************************************************
* Functions
******************************************************************************/
const isIterator = <A>(
o: (() => Iterator<A>) | Generator<A>,
): o is Generator<A> => Object.hasOwn(o, Symbol.iterator);
export function make<A>(
fa: (() => Iterator<A>) | Generator<A>,
): Iterable<A> {
if (isIterator(fa)) {
return fa;
}
return { [Symbol.iterator]: fa };
}
export function of<A>(...a: A[]): Iterable<A> {
return make(function* () {
let index = -1;
const length = a.length;
while (++index < length) {
yield a[index];
}
});
}
export function ap<A, I>(
tfai: Iterable<(a: A) => I>,
): (ta: Iterable<A>) => Iterable<I> {
return (ta) =>
make(function* () {
for (const fai of tfai) {
for (const a of ta) {
yield fai(a);
}
}
});
}
export function map<A, I>(fai: (a: A) => I): (ta: Iterable<A>) => Iterable<I> {
return (ta) =>
make(function* () {
for (const a of ta) {
yield fai(a);
}
});
}
export function join<A>(tta: Iterable<Iterable<A>>): Iterable<A> {
return make(function* () {
for (const ta of tta) {
for (const a of ta) {
yield a;
}
}
});
}
export function chain<A, I>(
fati: (a: A) => Iterable<I>,
): (ta: Iterable<A>) => Iterable<I> {
return (ta) =>
make(function* () {
for (const a of ta) {
for (const i of fati(a)) {
yield i;
}
}
});
}
/*******************************************************************************
* Modules
******************************************************************************/
export const Functor: TC.Functor<URI> = { map };
export const Apply: TC.Apply<URI> = { ap, map };
export const Applicative: TC.Applicative<URI> = { of, ap, map };
export const Chain: TC.Chain<URI> = { ap, map, chain };
export const Monad: TC.Monad<URI> = { of, ap, map, join, chain };
/*******************************************************************************
* Derived Functions
******************************************************************************/
export const { Do, bind, bindTo } = createDo(Monad);
export const sequenceTuple = createSequenceTuple(Apply);
export const sequenceStruct = createSequenceStruct(Apply);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment