-
Notifications
You must be signed in to change notification settings - Fork 0
WIP: Do, bind, bindTo #3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
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