Open19

【TypeScript】カリー化関数を書きたくなった

おーみーおーみー

実際の型がこちら。TypeScript 4.1 で Conditional Types での再帰の制限が緩和されたおかげで素直に再帰しても怒られが発生しない。

type Curry <P extends unknown[], R> = P extends { length: 1 } ? (p: P[0]) => R : P extends [...infer B, infer T] ? Curry<B, (t: T) => R> : never;
おーみーおーみー

再帰するたびに引数リスト P の末尾が削られて R にカリー化された関数の形で溜まっていく.

おーみーおーみー

タプルの末尾以外で ... が使えるのも TypeScript 4.0 のVariadic Tuple Typesのおかげ.

おーみーおーみー

extends { length: 1 } するという [T] の判別の仕方,個人的には斬新だと思っているがたぶん既出そう.

おーみーおーみー

実装する方法が全くわからないので関数型プログラミングライブラリとして著名なRamda.jsのソースを読もうとする.ちなみにRamda.jsは使ったことがない.

おーみーおーみー
おーみーおーみー
import _curry1 from './internal/_curry1';

というコードがあって怖気づく.そんな大層な関数を作らなければならないなんてやばいね!とおもう.

おーみーおーみー

せっかくなので Deno を使おうと試みている.さらにせっかくなので VSCode Remote Container に突っ込もうと画策している.Yak shavingの王とは私のことだ.

おーみーおーみー

JavaScript/TypeScript筋に比べてDocker力がぜんぜん無いので学ばなければならないとおもった.

おーみーおーみー

just-curryの実装を見て,Function.length というプロパティがあることを知った.たしかにJSが動的型付けとはいえ,関数が生成される時には仮引数の数は確定している (可変長引数は知らん).

おーみーおーみー

というか可変長引数はargs的な感じで配列として1つにまとまるから普通に1個カウントな気がする.

おーみーおーみー

just-curryの実装が生JSかつthisとargumentsが乱舞する感じでしかも再帰沼が深すぎてTSが死ぬ.