Merge pull request #26488 from googol/ramda-pipe-compose-K-P

Ramda: Add pipeK, pipeP, composeK, composeP
This commit is contained in:
Mine Starks
2018-06-13 09:36:16 -07:00
committed by GitHub
2 changed files with 323 additions and 2 deletions
+204 -2
View File
@@ -420,12 +420,72 @@ declare namespace R {
fn0: (x0: V0, x1: V1, x2: V2) => T1): (x0: V0, x1: V1, x2: V2) => T6;
/**
* TODO composeK
* Returns the right-to-left Kleisli composition of the provided functions, each of which must return a value of a type supported by chain.
* The typings only support arrays for now.
* All functions must be unary.
* R.composeK(h, g, f) is equivalent to R.compose(R.chain(h), R.chain(g), f).
*/
composeK<V0, T1>(
fn0: (x0: V0) => T1[]): (x0: V0) => T1[];
composeK<V0, T1, T2>(
fn1: (x: T1) => T2[],
fn0: (x0: V0) => T1[]): (x0: V0) => T2[];
composeK<V0, T1, T2, T3>(
fn2: (x: T2) => T3[],
fn1: (x: T1) => T2[],
fn0: (x: V0) => T1[]): (x: V0) => T3[];
composeK<V0, T1, T2, T3, T4>(
fn3: (x: T3) => T4[],
fn2: (x: T2) => T3[],
fn1: (x: T1) => T2[],
fn0: (x: V0) => T1[]): (x: V0) => T4[];
composeK<V0, T1, T2, T3, T4, T5>(
fn4: (x: T4) => T5[],
fn3: (x: T3) => T4[],
fn2: (x: T2) => T3[],
fn1: (x: T1) => T2[],
fn0: (x: V0) => T1[]): (x: V0) => T5[];
composeK<V0, T1, T2, T3, T4, T5, T6>(
fn5: (x: T5) => T6[],
fn4: (x: T4) => T5[],
fn3: (x: T3) => T4[],
fn2: (x: T2) => T3[],
fn1: (x: T1) => T2[],
fn0: (x: V0) => T1[]): (x: V0) => T6[];
/**
* TODO composeP
* Performs right-to-left composition of one or more Promise-returning functions.
* All functions must be unary.
*/
composeP<V0, T1>(
fn0: (x0: V0) => Promise<T1>): (x0: V0) => Promise<T1>;
composeP<V0, T1, T2>(
fn1: (x: T1) => Promise<T2>,
fn0: (x0: V0) => Promise<T1>): (x0: V0) => Promise<T2>;
composeP<V0, T1, T2, T3>(
fn2: (x: T2) => Promise<T3>,
fn1: (x: T1) => Promise<T2>,
fn0: (x: V0) => Promise<T1>): (x: V0) => Promise<T3>;
composeP<V0, T1, T2, T3, T4>(
fn3: (x: T3) => Promise<T4>,
fn2: (x: T2) => Promise<T3>,
fn1: (x: T1) => Promise<T2>,
fn0: (x: V0) => Promise<T1>): (x: V0) => Promise<T4>;
composeP<V0, T1, T2, T3, T4, T5>(
fn4: (x: T4) => Promise<T5>,
fn3: (x: T3) => Promise<T4>,
fn2: (x: T2) => Promise<T3>,
fn1: (x: T1) => Promise<T2>,
fn0: (x: V0) => Promise<T1>):
(x: V0) => Promise<T5>;
composeP<V0, T1, T2, T3, T4, T5, T6>(
fn5: (x: T5) => Promise<T6>,
fn4: (x: T4) => Promise<T5>,
fn3: (x: T3) => Promise<T4>,
fn2: (x: T2) => Promise<T3>,
fn1: (x: T1) => Promise<T2>,
fn0: (x: V0) => Promise<T1>):
(x: V0) => Promise<T6>;
/**
* Returns a new list consisting of the elements of the first list followed by the elements
@@ -1501,6 +1561,148 @@ declare namespace R {
fn8: (x: T8) => T9,
fn9: (x: T9) => T10): (x0: V0, x1: V1, x2: V2) => T10;
/*
* Returns the left-to-right Kleisli composition of the provided functions, each of which must return a value of a type supported by chain.
* The typings currently support arrays only as return values.
* All functions need to be unary.
* R.pipeK(f, g, h) is equivalent to R.pipe(f, R.chain(g), R.chain(h)).
*/
pipeK<V0, T1>(
fn0: (x0: V0) => T1[]): (x0: V0) => T1[];
pipeK<V0, T1, T2>(
fn0: (x0: V0) => T1[],
fn1: (x: T1) => T2[]): (x0: V0) => T2[];
pipeK<V0, T1, T2, T3>(
fn0: (x: V0) => T1[],
fn1: (x: T1) => T2[],
fn2: (x: T2) => T3[]): (x: V0) => T3[];
pipeK<V0, T1, T2, T3, T4>(
fn0: (x: V0) => T1[],
fn1: (x: T1) => T2[],
fn2: (x: T2) => T3[],
fn3: (x: T3) => T4[]): (x: V0) => T4[];
pipeK<V0, T1, T2, T3, T4, T5>(
fn0: (x: V0) => T1[],
fn1: (x: T1) => T2[],
fn2: (x: T2) => T3[],
fn3: (x: T3) => T4[],
fn4: (x: T4) => T5[]): (x: V0) => T5[];
pipeK<V0, T1, T2, T3, T4, T5, T6>(
fn0: (x: V0) => T1[],
fn1: (x: T1) => T2[],
fn2: (x: T2) => T3[],
fn3: (x: T3) => T4[],
fn4: (x: T4) => T5[],
fn5: (x: T5) => T6[]): (x: V0) => T6[];
pipeK<V0, T1, T2, T3, T4, T5, T6, T7>(
fn0: (x: V0) => T1[],
fn1: (x: T1) => T2[],
fn2: (x: T2) => T3[],
fn3: (x: T3) => T4[],
fn4: (x: T4) => T5[],
fn5: (x: T5) => T6[],
fn: (x: T6) => T7[]): (x: V0) => T7[];
pipeK<V0, T1, T2, T3, T4, T5, T6, T7, T8>(
fn0: (x: V0) => T1[],
fn1: (x: T1) => T2[],
fn2: (x: T2) => T3[],
fn3: (x: T3) => T4[],
fn4: (x: T4) => T5[],
fn5: (x: T5) => T6[],
fn6: (x: T6) => T7[],
fn: (x: T7) => T8[]): (x: V0) => T8[];
pipeK<V0, T1, T2, T3, T4, T5, T6, T7, T8, T9>(
fn0: (x0: V0) => T1[],
fn1: (x: T1) => T2[],
fn2: (x: T2) => T3[],
fn3: (x: T3) => T4[],
fn4: (x: T4) => T5[],
fn5: (x: T5) => T6[],
fn6: (x: T6) => T7[],
fn7: (x: T7) => T8[],
fn8: (x: T8) => T9[]): (x0: V0) => T9[];
pipeK<V0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(
fn0: (x0: V0) => T1[],
fn1: (x: T1) => T2[],
fn2: (x: T2) => T3[],
fn3: (x: T3) => T4[],
fn4: (x: T4) => T5[],
fn5: (x: T5) => T6[],
fn6: (x: T6) => T7[],
fn7: (x: T7) => T8[],
fn8: (x: T8) => T9[],
fn9: (x: T9) => T10[]): (x0: V0) => T10[];
/*
* Performs left-to-right composition of one or more Promise-returning functions.
* All functions need to be unary.
*/
pipeP<V0, T1>(
fn0: (x0: V0) => Promise<T1>): (x0: V0) => Promise<T1>;
pipeP<V0, T1, T2>(
fn0: (x0: V0) => Promise<T1>,
fn1: (x: T1) => Promise<T2>): (x0: V0) => Promise<T2>;
pipeP<V0, T1, T2, T3>(
fn0: (x: V0) => Promise<T1>,
fn1: (x: T1) => Promise<T2>,
fn2: (x: T2) => Promise<T3>): (x: V0) => Promise<T3>;
pipeP<V0, T1, T2, T3, T4>(
fn0: (x: V0) => Promise<T1>,
fn1: (x: T1) => Promise<T2>,
fn2: (x: T2) => Promise<T3>,
fn3: (x: T3) => Promise<T4>): (x: V0) => Promise<T4>;
pipeP<V0, T1, T2, T3, T4, T5>(
fn0: (x: V0) => Promise<T1>,
fn1: (x: T1) => Promise<T2>,
fn2: (x: T2) => Promise<T3>,
fn3: (x: T3) => Promise<T4>,
fn4: (x: T4) => Promise<T5>): (x: V0) => Promise<T5>;
pipeP<V0, T1, T2, T3, T4, T5, T6>(
fn0: (x: V0) => Promise<T1>,
fn1: (x: T1) => Promise<T2>,
fn2: (x: T2) => Promise<T3>,
fn3: (x: T3) => Promise<T4>,
fn4: (x: T4) => Promise<T5>,
fn5: (x: T5) => Promise<T6>): (x: V0) => Promise<T6>;
pipeP<V0, T1, T2, T3, T4, T5, T6, T7>(
fn0: (x: V0) => Promise<T1>,
fn1: (x: T1) => Promise<T2>,
fn2: (x: T2) => Promise<T3>,
fn3: (x: T3) => Promise<T4>,
fn4: (x: T4) => Promise<T5>,
fn5: (x: T5) => Promise<T6>,
fn: (x: T6) => Promise<T7>): (x: V0) => Promise<T7>;
pipeP<V0, T1, T2, T3, T4, T5, T6, T7, T8>(
fn0: (x: V0) => Promise<T1>,
fn1: (x: T1) => Promise<T2>,
fn2: (x: T2) => Promise<T3>,
fn3: (x: T3) => Promise<T4>,
fn4: (x: T4) => Promise<T5>,
fn5: (x: T5) => Promise<T6>,
fn6: (x: T6) => Promise<T7>,
fn: (x: T7) => Promise<T8>): (x: V0) => Promise<T8>;
pipeP<V0, T1, T2, T3, T4, T5, T6, T7, T8, T9>(
fn0: (x0: V0) => Promise<T1>,
fn1: (x: T1) => Promise<T2>,
fn2: (x: T2) => Promise<T3>,
fn3: (x: T3) => Promise<T4>,
fn4: (x: T4) => Promise<T5>,
fn5: (x: T5) => Promise<T6>,
fn6: (x: T6) => Promise<T7>,
fn7: (x: T7) => Promise<T8>,
fn8: (x: T8) => Promise<T9>): (x0: V0) => Promise<T9>;
pipeP<V0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(
fn0: (x0: V0) => Promise<T1>,
fn1: (x: T1) => Promise<T2>,
fn2: (x: T2) => Promise<T3>,
fn3: (x: T3) => Promise<T4>,
fn4: (x: T4) => Promise<T5>,
fn5: (x: T5) => Promise<T6>,
fn6: (x: T6) => Promise<T7>,
fn7: (x: T7) => Promise<T8>,
fn8: (x: T8) => Promise<T9>,
fn9: (x: T9) => Promise<T10>): (x0: V0) => Promise<T10>;
/**
* Returns a new list by plucking the same named property off all objects in the list supplied.
*/
+119
View File
@@ -186,6 +186,68 @@ class F2 {
const g_res: boolean = g([1, 2, 10, 13]);
};
/* composeK */
() => {
const get = (prop: string) => (obj: any): any[] => {
const propVal = obj[prop];
if (propVal) {
return [propVal];
} else {
return [];
}
};
const getStateCode: (input: any) => any[] = R.composeK(
R.compose((val) => [val], R.toUpper),
get('state'),
get('address'),
get('user'),
);
getStateCode({ user: { address: { state: "ny" } } }); // => []
getStateCode({}); // => []
const nextThree = (num: number): number[] => ([num, num + 1, num + 2]);
const onlyOverNine = (num: number): number[] => num > 9 ? [num] : [];
const toString = (input: any): string[] => [`${input}`];
const split = (input: string): string[] => input.split('');
const composed: (num: number) => string[] = R.composeK(
split,
toString,
onlyOverNine,
nextThree,
);
};
/* composeP */
() => {
interface User {
name: string;
followers: string[];
}
interface Db {
users: { [index: string]: User };
}
const db: Db = {
users: {
JOE: {
name: 'Joe',
followers: ['STEVE', 'SUZY']
}
}
};
// We'll pretend to do a db lookup which returns a promise
const lookupUser = (userId: string): Promise<User> => Promise.resolve(db.users[userId]);
const lookupFollowers = (user: User): Promise<string[]> => Promise.resolve(user.followers);
lookupUser('JOE').then(lookupFollowers);
// followersForUser :: String -> Promise [UserId]
const followersForUser: (input: string) => Promise<string[]> = R.composeP(lookupFollowers, lookupUser);
followersForUser('JOE').then(followers => console.log('Followers:', followers));
// Followers: ["STEVE","SUZY"]
};
/* pipe */
() => {
const func: (x: number) => string = R.pipe(double, double, shout);
@@ -201,6 +263,63 @@ class F2 {
const fr: number = f(3, 4); // -(3^4) + 1
};
/* pipeK */
() => {
const parseJson = (input: string): any[] => {
try {
return [JSON.parse(input)];
} catch (e) {
return [];
}
};
const get = (prop: string) => (obj: any): any[] => {
const propVal = obj[prop];
if (propVal) {
return [propVal];
} else {
return [];
}
};
const getStateCode: (input: string) => string[] = R.pipeK(
parseJson,
get('user'),
get('address'),
get('state'),
R.compose((val) => [val], R.toUpper)
);
getStateCode('{"user":{"address":{"state":"ny"}}}');
// => Just('NY')
getStateCode('[Invalid JSON]');
// => Nothing()
};
/* pipeP */
() => {
interface User {
followers: string[];
name: string;
}
const db = {
getUserById(userName: string): Promise<User> {
return Promise.resolve({
name: 'Jon',
followers: [
'Samwell',
'Edd',
'Grenn',
],
});
},
getFollowers(user: User): Promise<string[]> {
return Promise.resolve(user.followers);
},
};
const followersForUser: (userName: string) => Promise<string[]> = R.pipeP(db.getUserById, db.getFollowers);
};
() => {
R.invoker(1, "slice")(6, "abcdefghijklm");
R.invoker(2, "slice")(6)(8, "abcdefghijklm");