Функция подписи Тап (К-комбинатор)

Я читал в книге, что функция подписи функции крана (также называемой K-Combinator) ниже:

tap :: (a -> *) -> a -> a

"Эта функция принимает входной объект a и функцию, которая выполняет некоторое действие над a. Она выполняет данную функцию с предоставленным объектом, а затем возвращает объект".

  1. Может кто-нибудь помочь мне объяснить, что означает звезда (*) в сигнатуре функции?
  2. Правильно ли реализовано ниже?
  3. Если все три реализации верны, то какую следует использовать когда? Есть примеры?

Реализация 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 Этот пример кода взят из моей старой статьи о Рамде.

Другие вопросы по тегам