🍛
カリー化,高階関数,ファクトリ関数,依存性の逆転
依存性の逆転を関数型で書く
これを読み解く。
難しかったら次の カリー化と高階関数へ 。
type QueryFn = (sql: string) => Promise<any>;
const makeGetUser =
(query: QueryFn) =>
async (id: number): Promise<any> => {
const sql = `SELECT * FROM users WHERE id = ${id}`;
return query(sql);
};
// ファクトリ関数
function createUserService(query: QueryFn) {
const getUser = makeGetUser(query);
return {
getUser,
};
}
// MySQL 実装
const queryMySql: QueryFn = async (sql) => {
console.log(`→ MySQL 実行: ${sql}`);
// MySQL ドライバ呼び出し…
return { id: 1, name: "Taro" };
};
// PostgreSQL 実装(新しく追加したい DB)
const queryPostgres: QueryFn = async (sql) => {
console.log(`→ PostgreSQL 実行: ${sql}`);
// PostgreSQL ドライバ呼び出し…
return { id: 2, name: "Hanako" };
};
(async () => {
const mysqlService = createUserService(queryMySql);
const mysqlUser = await mysqlService.getUser(1);
console.info(mysqlUser);
const pgService = createUserService(queryPostgres);
const pgUser = await pgService.getUser(2);
console.info(pgUser);
})();
→ MySQL 実行: SELECT * FROM users WHERE id = 1
{ id: 1, name: 'Taro' }
→ PostgreSQL 実行: SELECT * FROM users WHERE id = 2
{ id: 2, name: 'Hanako' }
カリー化と高階関数
難しかったら次の カリー化へ 。
function add(a: number, b: number): number {
return a + b;
}
// カリー化された高階関数
function curry2<A, B, R>(
fn: (a: A, b: B) => R
): (a: A) => (b: B) => R {
return (a: A) => (b: B) => fn(a, b);
}
const curriedAdd = curry2(add);
const add5 = curriedAdd(5);
console.log(add5(3));
カリー化
const foo = (x: number) => (y: number) => x + y;
const bar = foo(1);
console.info(`bar(2): ${bar(2)}`);
console.info(`foo(1)(2): ${foo(1)(2)}`);
bar(2): 3
foo(1)(2): 3
さらに詳しく・・・
const gx = (x: number) => {
console.log("outer got", x);
return (y: number) => {
console.log("inner got", y);
return x + y;
};
};
// これを簡潔に書くと
const gy = (x: number) => (y: number) => x + y;
console.info(`gx(1)(2): ${gx(1)(2)}`);
console.info(`gy(1)(2): ${gy(1)(2)}`);
outer got 1
inner got 2
gx(1)(2): 3
gy(1)(2): 3
関数型への動機
Discussion