Skip to content

Instantly share code, notes, and snippets.

@saulshanabrook
Created September 24, 2019 14:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save saulshanabrook/d1d2eb7b785e400f7a2b906b6bac0462 to your computer and use it in GitHub Desktop.
Save saulshanabrook/d1d2eb7b785e400f7a2b906b6bac0462 to your computer and use it in GitHub Desktop.
type Middleware<A, B, C, D> = Fn<A, [B, Fn<C, D>] | null>;
function applyMiddleware<A, B, C, D>(
middleware: Middleware<A, B, C, D>,
b_c: Fn<B, C>
): Fn<A, D | null> {
return a => {
const res = middleware(a);
if (!res) {
return null;
}
const [b, c_d] = res;
return c_d(b_c(b));
};
}
function composeMiddleware<A, B, C, D, E, F>(
l: Middleware<A, B, C, D>,
r: Middleware<B, E, F, C>
): Middleware<A, E, F, D> {
return a => {
const lRes = l(a);
if (!lRes) {
return null;
}
const [b, c_d] = lRes;
const rRes = r(b);
if (!rRes) {
return null;
}
const [e, f_c] = rRes;
return [e, f => c_d(f_c(f))];
};
}
type WithCost<T> = T & { cost: number };
function incrementCostMiddleware<B, C>(): Middleware<
WithCost<B>,
B,
C,
WithCost<C>
> {
return ({ cost, ...rest }) => [rest as any, u => ({ cost: cost + 1, ...u })];
}
type WithURLString<T> = T & { url: string };
type WithURL<T> = T & { url: URL };
function parseURLMiddleware<B, C>(): Middleware<
WithURLString<B>,
WithURL<B>,
C,
C
> {
return ({ url, ...rest }) => {
try {
return [
{ url: new URL(url), ...rest } as any,
res => res
];
} catch {
return null;
}
};
}
const fn = applyMiddleware(
composeMiddleware(parseURLMiddleware(), incrementCostMiddleware()),
({ a, url }: { a: number, url: URL }) => ({ a, b: "hi", url })
);
const res = fn({ a: 10, cost: 50 });
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment