Conversation
9e1ab00 to
b039bbe
Compare
|
So, I guess your question is why isn't the bind type definition working. The implementation in this PR is this: export function bind<U extends Kind>(M: Chain<U>):
<N extends string, A, B, C, I, J = never, K = never, D = unknown, E = unknown>
(name: Exclude<N, keyof A>, f: (a: A) => $<U, [I, J, K], [D], [E]>) =>
<B, C>
(ma: $<U, [A, B, C], [D], [E]>) =>
$<U, [{ readonly [K in keyof A | N]: K extends keyof A ? A[K] : I }], [D], [E]>
{
return (name, f) =>
// @ts-expect-error <type-errors> TODO: @baetheus
M.chain((a) => M.map((b) => Object.assign({}, a, { [name]: b }) as any)(f(a))
);
}The first problem I see is that there are several shadowed generics. The first curried function declares
To illustrate I've pasted the new import type { $, Kind } from "./kind.ts";
import type { Wrappable } from "./wrappable.ts";
import type { Mappable } from "./mappable.ts";
import { pipe } from "./fn.ts";
/**
* A Flatmappable structure.
*/
export type Flatmappable<U extends Kind> = {
readonly flatmap: <A, I, J = never, K = never, L = unknown, M = unknown>(
fati: (a: A) => $<U, [I, J, K], [L], [M]>,
) => <B = never, C = never, D = unknown, E = unknown>(
ta: $<U, [A, B, C], [D], [E]>,
) => $<U, [I, B | J, C | K], [D & L], [E & M]>;
};
/**
* Create a tap function for a structure with instances of Wrappable and
* Flatmappable. A tap function allows one to break out of the functional
* codeflow. It is generally not advised to use tap for code flow but to
* consider an escape hatch to do things like tracing or logging.
*
* @since 2.0.0
*/
export function createTap<U extends Kind>(
{ wrap, flatmap }: Wrappable<U> & Flatmappable<U>,
): <A>(
fn: (value: A) => void,
) => <B = never, C = never, D = unknown, E = unknown>(
ua: $<U, [A, B, C], [D], [E]>,
) => $<U, [A, B, C], [D], [E]> {
return (fn) =>
flatmap((a) => {
fn(a);
return wrap(a);
});
}
/**
* Create a bind function for a structure with instances of Mappable and
* Flatmappable. A bind function allows one to flatmap into named fields in a
* struct, collecting values from the result of the flatmap in the order that
* they are completed.
*
* @since 2.0.0
*/
export function createBind<U extends Kind>(
{ flatmap, map }: Flatmappable<U> & Mappable<U>,
): <N extends string, A, I, J = never, K = never, L = unknown, M = unknown>(
name: Exclude<N, keyof A>,
faui: (a: A) => $<U, [I, J, K], [L], [M]>,
) => <B = never, C = never, D = unknown, E = unknown>(
ua: $<U, [A, B, C], [D], [E]>,
) => $<
U,
[{ readonly [K in keyof A | N]: K extends keyof A ? A[K] : I }, B | J, C | K],
[D & L],
[E & M]
> {
return (name, fai) =>
flatmap((a) =>
pipe(
fai(a),
// deno-lint-ignore no-explicit-any
map((b) => Object.assign({}, a, { [name]: b }) as any),
)
);
} |
Refactor looks real neat! |
|
It's pretty much the same, I think.. Just no interface for Do, Bind, and BindTo |
|
I think I just noticed an issue with tap though. One might lose information from an adt like Datum. |
|
Noo.. wait, maybe not.. |
Implements the Do/bind syntax for fun