Skip to content

Commit

Permalink
fix: Replace empty tuple with never[] (#198)
Browse files Browse the repository at this point in the history
  • Loading branch information
MikuroXina committed May 11, 2024
1 parent 712fdb9 commit 643836a
Show file tree
Hide file tree
Showing 18 changed files with 75 additions and 60 deletions.
13 changes: 7 additions & 6 deletions src/binary-heap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,12 +161,13 @@ const downHeap =
* @param heap - To be inserted.
* @returns The inserted new heap.
*/
export const insert = <T>(item: T) => <S>(heap: BinaryHeap<S, T>): Mut<S, []> =>
modifyMutRef(heap)((heap) => {
heap.items.push(item);
upHeap(heap.items.length - 1)(heap.order)(heap.items);
return heap;
});
export const insert =
<T>(item: T) => <S>(heap: BinaryHeap<S, T>): Mut<S, never[]> =>
modifyMutRef(heap)((heap) => {
heap.items.push(item);
upHeap(heap.items.length - 1)(heap.order)(heap.items);
return heap;
});

/**
* Removes the minimum item from the heap. It takes `O(log n)`, but also takes `O(n)` to copy the items.
Expand Down
24 changes: 14 additions & 10 deletions src/cat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,15 +70,17 @@ export interface CatT<M, CTX> {
* @param computation - The computation to run.
* @returns A new `CatT` with modified environment.
*/
readonly run: (computation: Get1<M, []>) => CatT<M, CTX>;
readonly run: (computation: Get1<M, never[]>) => CatT<M, CTX>;

/**
* Runs the computation with the context.
*
* @param computation - The computation to run.
* @returns A new `CatT` with modified environment.
*/
readonly runWith: (computation: (ctx: CTX) => Get1<M, []>) => CatT<M, CTX>;
readonly runWith: (
computation: (ctx: CTX) => Get1<M, never[]>,
) => CatT<M, CTX>;

/**
* Binds a new value wrapped by the monad, calculated from `ctx` by `fn`.
Expand All @@ -101,7 +103,7 @@ export interface CatT<M, CTX> {
*/
readonly when: (
cond: (ctx: CTX) => boolean,
computation: (ctx: CTX) => Get1<M, []>,
computation: (ctx: CTX) => Get1<M, never[]>,
) => CatT<M, CTX>;

/**
Expand All @@ -113,7 +115,7 @@ export interface CatT<M, CTX> {
*/
readonly loop: <S>(
initState: S,
body: (state: S, ctx: CTX) => Get1<M, ControlFlow<[], S>>,
body: (state: S, ctx: CTX) => Get1<M, ControlFlow<never[], S>>,
) => CatT<M, CTX>;

/**
Expand All @@ -125,7 +127,7 @@ export interface CatT<M, CTX> {
*/
readonly while: (
cond: (ctx: CTX) => boolean,
body: (ctx: CTX) => Get1<M, []>,
body: (ctx: CTX) => Get1<M, never[]>,
) => CatT<M, CTX>;

/**
Expand All @@ -137,7 +139,7 @@ export interface CatT<M, CTX> {
*/
readonly foreach: <T>(
iter: List<T>,
body: (item: T, ctx: CTX) => Get1<M, []>,
body: (item: T, ctx: CTX) => Get1<M, never[]>,
) => CatT<M, CTX>;

/**
Expand Down Expand Up @@ -218,11 +220,13 @@ export const catT =
),
loop: <S>(
initialState: S,
body: (state: S, ctx: CTX) => Get1<M, ControlFlow<[], S>>,
body: (state: S, ctx: CTX) => Get1<M, ControlFlow<never[], S>>,
): CatT<M, CTX> => {
const go = (state: S): Get1<M, CTX> =>
monad.flatMap((c: CTX) =>
monad.flatMap((flow: ControlFlow<[], S>): Get1<M, CTX> =>
monad.flatMap((
flow: ControlFlow<never[], S>,
): Get1<M, CTX> =>
isBreak(flow) ? monad.pure(c) : go(flow[1])
)(body(state, c))
)(ctx);
Expand All @@ -239,7 +243,7 @@ export const catT =
},
foreach: <T>(
iter: List<T>,
body: (item: T, ctx: CTX) => Get1<M, []>,
body: (item: T, ctx: CTX) => Get1<M, never[]>,
): CatT<M, CTX> =>
catT(monad)(
foldL((acc: Get1<M, CTX>) => (item: T) =>
Expand All @@ -258,7 +262,7 @@ export const catT =
* @param monad - The monad implementation for `M`.
* @returns A new `CatT`.
*/
export const doVoidT = <M>(monad: Monad<M>): CatT<M, []> =>
export const doVoidT = <M>(monad: Monad<M>): CatT<M, never[]> =>
catT(monad)(monad.pure([]));

/**
Expand Down
2 changes: 1 addition & 1 deletion src/control-flow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export const newBreak = <B>(b: B): Break<B> => [breakSymbol, b];
/**
* An utility type `ControlFlow<B, C>`, which tells an operation whether it should exit early or go on. It's more clear than `boolean` or `Result` to show your code flow control explicity.
*/
export type ControlFlow<B, C = []> = Continue<C> | Break<B>;
export type ControlFlow<B, C = never[]> = Continue<C> | Break<B>;

export const isContinue = <B, C>(cf: ControlFlow<B, C>): cf is Continue<C> =>
cf[0] === continueSymbol;
Expand Down
11 changes: 7 additions & 4 deletions src/free.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,14 @@ Deno.test("hello language", async (t) => {
},
);

const hello: Free<HelloLangHkt, []> = liftF({ type: "Hello", next: [] });
const hey: Free<HelloLangHkt, []> = liftF({ type: "Hey", next: [] });
const yearsOld = (years: number): Free<HelloLangHkt, []> =>
const hello: Free<HelloLangHkt, never[]> = liftF({
type: "Hello",
next: [],
});
const hey: Free<HelloLangHkt, never[]> = liftF({ type: "Hey", next: [] });
const yearsOld = (years: number): Free<HelloLangHkt, never[]> =>
liftF({ type: "YearsOld", years, next: [] });
const bye: Free<HelloLangHkt, []> = liftF({ type: "Bye" });
const bye: Free<HelloLangHkt, never[]> = liftF({ type: "Bye" });

const m = freeMonad<HelloLangHkt>();

Expand Down
14 changes: 7 additions & 7 deletions src/graph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ export type CycleError = Readonly<{
export const topologicalSort = (graph: Graph): Result<CycleError, Vertex[]> => {
const nodes = [] as Vertex[];
const visited = new Set<Vertex>();
const visit = (visiting: Vertex): Result<CycleError, []> => {
const visit = (visiting: Vertex): Result<CycleError, never[]> => {
visited.add(visiting);
for (const next of toIterator(adjsFrom(visiting)(graph))) {
if (visited.has(next)) {
Expand All @@ -293,7 +293,7 @@ export const topologicalSort = (graph: Graph): Result<CycleError, Vertex[]> => {
}
}
nodes.push(visiting);
return ok([] as []);
return ok([]);
};
for (let start = 0 as Vertex; start < graph.length; ++start) {
if (!visited.has(start)) {
Expand Down Expand Up @@ -503,16 +503,16 @@ export const dijkstra =
)
)
.finishM(({ heap }) => {
const body: Mut<S, []> = doT(m)
const body: Mut<S, never[]> = doT(m)
.addM("min", BinaryHeap.popMin(heap))
.finishM(({ min }) => {
const [visiting, visitingDist] = unwrap(min);
visited.add(visiting);
dist[visiting] = visitingDist;
return mapMIgnore(foldable, m)(
(next: Vertex): Mut<S, []> => {
(next: Vertex): Mut<S, never[]> => {
if (visited.has(next)) {
return m.pure([] as []);
return m.pure([]);
}
const nextWeight = edgeWeight([
visiting,
Expand All @@ -530,10 +530,10 @@ export const dijkstra =
});
const loop = (
heap: BinaryHeap.BinaryHeap<S, WeightedVertex>,
): Mut<S, []> =>
): Mut<S, never[]> =>
m.flatMap((wasEmpty) =>
wasEmpty
? m.pure([] as [])
? m.pure([])
: m.flatMap(() => loop(heap))(body)
)(BinaryHeap.isEmpty(heap));
return loop(heap);
Expand Down
2 changes: 1 addition & 1 deletion src/mut.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Deno.test("counter", () => {
.addM("count", newMutRef(0))
.runWith(
({ count }) => {
const loop = (i: number): Mut<S, []> =>
const loop = (i: number): Mut<S, never[]> =>
i <= 0 ? m.pure([]) : m.flatMap(() => loop(i - 1))(
modifyMutRef(count)((c: number) => c + 1),
);
Expand Down
14 changes: 8 additions & 6 deletions src/mut.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ export const readMutRef = <S, A>(ref: MutRef<S, A>): Mut<S, A> =>
* @returns The writing operation.
*/
export const writeMutRef =
<S, A>(ref: MutRef<S, A>) => (newValue: A): Mut<S, []> => (thread) => {
<S, A>(ref: MutRef<S, A>) => (newValue: A): Mut<S, never[]> => (thread) => {
writeThreadVar(ref)(newValue)(thread);
return wrapVar([]);
};
Expand All @@ -202,7 +202,8 @@ export const writeMutRef =
* @returns The modifying operation.
*/
export const modifyMutRef =
<S, A>(ref: MutRef<S, A>) => (modifier: (oldValue: A) => A): Mut<S, []> =>
<S, A>(ref: MutRef<S, A>) =>
(modifier: (oldValue: A) => A): Mut<S, never[]> =>
doT(monad<S>())
.addM("value", readMutRef(ref))
.addWith("modified", ({ value }) => modifier(value))
Expand All @@ -214,7 +215,8 @@ export const modifyMutRef =
* @param ref - A target to invalidate.
* @returns The dropping operation.
*/
export const dropMutRef = <S, A>(ref: MutRef<S, A>): Mut<S, []> => (thread) => {
dropThreadVar(ref)(thread);
return wrapVar([]);
};
export const dropMutRef =
<S, A>(ref: MutRef<S, A>): Mut<S, never[]> => (thread) => {
dropThreadVar(ref)(thread);
return wrapVar([]);
};
2 changes: 1 addition & 1 deletion src/serial.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Deno.test("multiple integers", async () => {
.run(encU8(3))
.run(encU16Be(1))
.run(encU32Be(4))
.finish<[]>(() => []);
.finish(() => []);
const buf = await runCode(code);
const array = new Uint8Array(buf);
assertEquals(array[0], 3);
Expand Down
19 changes: 11 additions & 8 deletions src/serial.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ export const fillWithBuildStep =
/**
* An identity build step that does nothing.
*/
export const finalStep: BuildStep<[]> = ([start]) =>
export const finalStep: BuildStep<never[]> = ([start]) =>
Promise.resolve({
type: buildDoneNominal,
nextFreeIndex: start,
Expand All @@ -171,7 +171,7 @@ export type Builder = <I>(step: BuildStep<I>) => BuildStep<I>;
* @param builder - An execution target.
* @returns The identity build step, but transformed by the builder.
*/
export const runBuilder = (builder: Builder): BuildStep<[]> =>
export const runBuilder = (builder: Builder): BuildStep<never[]> =>
builder(finalStep);

/**
Expand Down Expand Up @@ -571,7 +571,7 @@ export type CodeM<T> = readonly [result: T, builder: Builder];
/**
* Encoded result, having a void computation result.
*/
export type Code = CodeM<[]>;
export type Code = CodeM<never[]>;
/**
* An `Encoder` that encodes the value of `T` into a `Code`.
*/
Expand Down Expand Up @@ -698,7 +698,7 @@ export const flushCode: Code = tell(flush);
/**
* Encodes nothing. It is an identity encoder.
*/
export const encUnit: Encoder<[]> = compose(tell)(() => empty);
export const encUnit: Encoder<never[]> = compose(tell)(() => empty);

/**
* Encodes a number as a signed 8-bit integer.
Expand Down Expand Up @@ -1009,8 +1009,11 @@ export const decodeRaw: Decoder<DataView> = (ctx) => () => (onS) =>
* @returns The overwriting decoder.
*/
export const putRaw =
(data: DataView) => (offset: number): Decoder<[]> => (ctx) => () => (onS) =>
onS({ ...ctx, input: data, offset })([]);
(data: DataView) =>
(offset: number): Decoder<never[]> =>
(ctx) =>
() =>
(onS) => onS({ ...ctx, input: data, offset })([]);

/**
* Labels the stack trace with `note`. It is used for reporting an error on failure.
Expand Down Expand Up @@ -1064,7 +1067,7 @@ export const flatMapDecoder =
* @returns The failing decoder.
*/
export const failDecoder =
(message: string): Decoder<[]> => (ctx) => (onF) => () =>
(message: string): Decoder<never[]> => (ctx) => (onF) => () =>
onF(ctx)([])("read failure: " + message);

export interface DecoderHkt extends Hkt1 {
Expand Down Expand Up @@ -1338,7 +1341,7 @@ export const isolate =
* @param count - The number of bytes to skip.
* @returns The skipping decoder.
*/
export const skip = (count: number): Decoder<[]> =>
export const skip = (count: number): Decoder<never[]> =>
doT(monadForDecoder)
.addM("bytes", ensure(count))
.addM("curr", parsedBytes)
Expand Down
2 changes: 1 addition & 1 deletion src/type-class/abelian-group.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export interface AbelianGroup<G> extends Group<G> {
readonly [abelSymbol]: true;
}

export const trivialAbelianGroup: AbelianGroup<[]> = {
export const trivialAbelianGroup: AbelianGroup<never[]> = {
combine: () => [],
identity: [],
invert: () => [],
Expand Down
6 changes: 3 additions & 3 deletions src/type-class/foldable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ export const mapMIgnore = <T, M>(
) =>
<A, B>(
visitor: (a: A) => Get1<M, B>,
): (data: Get1<T, A>) => Get1<M, []> =>
foldable.foldR((x: A) => (k: Get1<M, []>) =>
monad.flatMap(() => k)(visitor(x))
): (data: Get1<T, A>) => Get1<M, never[]> =>
foldable.foldR((x: A) => (k: Get1<M, never[]>) =>
monad.flatMap<B, never[]>(() => k)(visitor(x))
)(monad.pure([]));
2 changes: 1 addition & 1 deletion src/type-class/group.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export const subtract = <G>(group: Group<G>) => (l: G) => (r: G): G =>
export const powi = <G>(group: Group<G>) => (base: G) => (exp: number): G =>
unwrap(powiEZ(toGroupExceptZero(group))(base)(exp));

export const trivialGroup: Group<[]> = {
export const trivialGroup: Group<never[]> = {
combine: () => [],
identity: [],
invert: () => [],
Expand Down
6 changes: 3 additions & 3 deletions src/type-class/monad-rec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ export const tailRec3 = <X, A, B, C>(
*/
export const forever =
<M>(m: MonadRec<M>) => <A, B>(op: Get1<M, A>): Get1<M, B> =>
m.tailRecM((state: []): Get1<M, ControlFlow<B, []>> =>
m.tailRecM((state: never[]): Get1<M, ControlFlow<B, never[]>> =>
replace(m)(newContinue(state))(op)
)([]);

Expand Down Expand Up @@ -127,9 +127,9 @@ export const whileSome =
*/
export const untilSome =
<M>(m: MonadRec<M>) => <T>(optionOp: Get1<M, Option<T>>): Get1<M, T> =>
m.tailRecM((_: []): Get1<M, ControlFlow<T, []>> =>
m.tailRecM((_: never[]): Get1<M, ControlFlow<T, never[]>> =>
m.map(
mapOrElse((): ControlFlow<T, []> => newContinue([]))(
mapOrElse((): ControlFlow<T, never[]> => newContinue([]))(
newBreak<T>,
),
)(optionOp)
Expand Down
2 changes: 1 addition & 1 deletion src/type-class/monoid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export const append = <T>(monoid: Monoid<T>) => (l: T) => (r: T): T =>
export const concat = <T>(monoid: Monoid<T>): (list: List.List<T>) => T =>
List.foldL(append(monoid))(monoid.identity);

export const trivialMonoid: Monoid<[]> = {
export const trivialMonoid: Monoid<never[]> = {
combine: () => [],
identity: [],
[semiGroupSymbol]: true,
Expand Down
10 changes: 6 additions & 4 deletions src/type-class/pure.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ export interface Pure<S> {
}

export const when =
<S>(app: Pure<S>) => (cond: boolean) => (op: Get1<S, []>): Get1<S, []> =>
cond ? op : app.pure([]);
<S>(app: Pure<S>) =>
(cond: boolean) =>
(op: Get1<S, never[]>): Get1<S, never[]> => cond ? op : app.pure([]);

export const unless =
<S>(app: Pure<S>) => (cond: boolean) => (op: Get1<S, []>): Get1<S, []> =>
cond ? app.pure([]) : op;
<S>(app: Pure<S>) =>
(cond: boolean) =>
(op: Get1<S, never[]>): Get1<S, never[]> => cond ? app.pure([]) : op;
2 changes: 1 addition & 1 deletion src/type-class/ring.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export interface Ring<R> {
readonly multiplication: Monoid<R>;
}

export const trivialRing: Ring<[]> = {
export const trivialRing: Ring<never[]> = {
additive: trivialAbelianGroup,
multiplication: trivialMonoid,
};
2 changes: 1 addition & 1 deletion src/writer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ Deno.test("tell with tower of hanoi", () => {
from: string,
to: string,
another: string,
): Writer<[string, string][], []> => {
): Writer<[string, string][], never[]> => {
if (height < 1) {
return pure(monoid)([]);
}
Expand Down

0 comments on commit 643836a

Please sign in to comment.