Tap的函数签名(K-combinator)

Jyo*_*Pal 3 javascript functional-programming function-signature k-combinator

我在一本书中读到过tap函数(也称为K-Combinator)的函数签名如下:

tap :: (a -> *) -> a -> a
Run Code Online (Sandbox Code Playgroud)

“该函数接受一个输入对象 a 和一个对 a 执行某些操作的函数。它使用提供的对象运行给定的函数,然后返回该对象。”

  1. 有人能帮我解释一下函数签名中星号(*)是什么意思吗?
  2. 下面的实现是否正确?
  3. 如果这三个实现都正确,那么应该在什么时候使用哪一个?有什么例子吗?

实施1:

const tap = fn => a => { fn(a); return a; };

tap((it) => console.log(it))(10); //10
Run Code Online (Sandbox Code Playgroud)

实施2:

const tap = a => fn => { fn(a); return a; }; 

tap(10)((it) => console.log(it)); //10
Run Code Online (Sandbox Code Playgroud)

实施3:

const tap = (a, fn) => {fn(a); return a; };

tap(10, (it) => console.log(it)); //10
Run Code Online (Sandbox Code Playgroud)

Sco*_*yet 6

这看起来很像Ramda 的定义。该*中有可能是一个错误。(免责声明:我是 Ramda 的作者之一。)它可能应该阅读

// tap :: (a -> b) -> a -> a
Run Code Online (Sandbox Code Playgroud)

像你的第一个实现:

const tap = fn => a => { fn(a); return a; };
Run Code Online (Sandbox Code Playgroud)

或 Ramda 的版本:

const tap = curry((fn, a) => { fn(a); return a; });
Run Code Online (Sandbox Code Playgroud)

匹配该签名,恕我直言,主要在调试上下文中很有用。我用它来临时将日志语句引入功能管道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]
);
Run Code Online (Sandbox Code Playgroud)

不过,这真的不是 K 组合子。


1此代码示例来自我在 Ramda 上的一篇旧文章