使用Ramda,您如何构成二进制函数?

时间:2018-11-27 04:13:12

标签: javascript functional-programming ramda.js

Ramda用R.equals提供了区分大小写的等于,但是我想要一个不区分大小写的相等测试。 Ramda还提供R.compose,但在Ramda构成中,假定最左边的参数是一元的。

我想做的是类似的事情

R.compose( R.equals(...), R.toLower )

但是,我想在二进制函数R.toLower上构成R.equals吗?

有没有一种方法可以做到这一点?喜欢的类型

(b->b->c) -> (a->b) => (a->a->c)

我想要的是类似Haskell的Data.Function.on的定义,

  

on b u x y将一元函数u应用于两个自变量xy的结果上运行二进制函数b。从相反的角度来看,它转换两个输入并组合输出。

2 个答案:

答案 0 :(得分:5)

编辑R.useWith与您要查找的内容非常接近:

  

接受一个函数fn和一个转换器函数列表,并返回一个新的curried函数。调用新函数时,它将使用包含由对新函数的连续参数调用每个提供的处理程序的结果组成的参数来调用函数fn。

所以您可以这样定义函数:

const equalsi = R.useWith(R.equals, [R.toLower, R.toLower]);

示例:

const equalsi = R.useWith(R.equals, [R.toLower, R.toLower]);

const check = (a, b) => console.log(`${a} = ${b}?`, equalsi(a, b));

check('aaa', 'aaa');
check('aaa', 'aa');
check('aAa', 'aaa');
check('aaa', 'aAa');
check('aba', 'aaa');
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.0/ramda.min.js"></script>

如果您希望使用与您提到的Haskell on函数等效的函数,则可以定义以下函数:

const on = (b, u) => R.useWith(b, [u, u]);
const equalsi = on(R.equals, R.toLower);

const check = (a, b) => console.log(`${a} = ${b}?`, equalsi(a, b));

check('aaa', 'aaa');
check('aaa', 'aa');
check('aAa', 'aaa');
check('aaa', 'aAa');
check('aba', 'aaa');
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.0/ramda.min.js"></script>


上一个答案

也许有一种更优雅的方法可以做到这一点,但这可行:

const equalsi = R.unapply(R.compose(
    R.apply(R.equals),
    R.map(R.toLower)
));

打破现状:

// [] -> Boolean
// Takes an array of two strings and returns true if they are equal
R.apply(R.equals)

// [] -> Boolean
// Takes an array of two strings, converts them to lowercase, and returns true
// if those lowercase strings are equal
R.compose(R.apply(R.equals), R.map(R.toLower))

// String -> String -> Boolean
// Takes two strings, converts them to lowercase, and returns true if those lowercase
// string are equal
R.unapply(R.compose(R.apply(R.equals), R.map(R.toLower)));

您还可以根据Ramda函数定义on函数,然后使用它:

const on = (b, u) => R.unapply(R.compose(R.apply(b), R.map(u));

const equalsi = on(R.equals, R.toLower);

答案 1 :(得分:4)

您可能还需要考虑eqBy

  

在其域中接受一个函数和两个值,如果值映射到共同域中的相同值,则返回true;否则,返回true。否则为假。

R.eqBy(R.toLower, 'a', 'A'); //=> true

示例:

console.log(R.eqBy(R.toLower, 'a', 'A'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.0/ramda.min.js"></script>