Функция подписи Тап (К-комбинатор)
Я читал в книге, что функция подписи функции крана (также называемой K-Combinator) ниже:
tap :: (a -> *) -> a -> a
"Эта функция принимает входной объект a и функцию, которая выполняет некоторое действие над a. Она выполняет данную функцию с предоставленным объектом, а затем возвращает объект".
- Может кто-нибудь помочь мне объяснить, что означает звезда (*) в сигнатуре функции?
- Правильно ли реализовано ниже?
- Если все три реализации верны, то какую следует использовать когда? Есть примеры?
Реализация 1:
const tap = fn => a => { fn(a); return a; };
tap((it) => console.log(it))(10); //10
Реализация 2:
const tap = a => fn => { fn(a); return a; };
tap(10)((it) => console.log(it)); //10
Реализация 3:
const tap = (a, fn) => {fn(a); return a; };
tap(10, (it) => console.log(it)); //10
1 ответ
Решение
Это очень похоже на определение Рамды. *
там, вероятно, ошибка. (Отказ от ответственности: я один из авторов Рамда.) Вероятно, следует прочитать
// tap :: (a -> b) -> a -> a
Реализация, подобная вашей первой:
const tap = fn => a => { fn(a); return a; };
или версия Рамды:
const tap = curry((fn, a) => { fn(a); return a; });
соответствуют этой подписи и полезны IMHO в основном в контекстах отладки. Я использую его для временного введения операторов логирования в функциональные конвейеры1:
// :: Map String User
const users = fetchUsersFromSomewhere();
// :: [Comment] -> [Number]
const userRatingForComments = R.pipe(
R.pluck('username'), // [Comment] -> [String]
R.tap(console.log), // for debugging, need to include `bind` in browser envs
// ^^^^^^^^^^^^^^^^^^
R.map(R.propOf(users)), // [String] -> [User]
R.pluck('rating') // [User] -> [Number]
);
Это действительно не K комбинатор, хотя.
1 Этот пример кода взят из моей старой статьи о Рамде.