【问题标题】:Using Ramda, how do you compose against binary functions?使用 Ramda,你如何组合二进制函数?
【发布时间】:2018-11-27 16:06:32
【问题描述】:

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

我想要做的是类似的事情

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

但是,我想在二进制函数R.equals 上编写R.toLower

有没有办法做到这一点?类型喜欢

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

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

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

【问题讨论】:

  • 你在 Ramda 失去了我。

标签: javascript functional-programming ramda.js


【解决方案1】:

编辑: R.useWith 非常接近您正在寻找的内容:

接受一个函数 fn 和一个转换器函数列表并返回一个新的柯里化函数。当新函数被调用时,它使用参数调用函数 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);

【讨论】:

  • 啊,聪明! (赞成)如果这是最佳答案,我会在一周内接受。这并不是完全可取的,因为我认为您在使用 apply/unapply 时会丢失很多打字,而且真的很难看。但仍然很聪明。
  • @EvanCarroll 谢谢!我使用useWith 找到了更好的方法。请看我上面的编辑。
  • 我多年来一直在说useWith 是一个更特定于 Ramda 的函数,并且与其他 FP 工具没有特别的联系。直到它与 Haskell 的 Data.Function.on 密切相关。非常好!但是,@customcommander 使用eqBy 的答案仍然更合适。
【解决方案2】:

还有eqBy你可能要考虑:

在其域中获取一个函数和两个值,如果这些值映射到 codomain 中的相同值,则返回 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>

【讨论】:

  • 是的,这正是eqBy 旨在解决的问题类型。
猜你喜欢
  • 2018-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-10
  • 2014-09-09
  • 2018-03-16
  • 2018-12-15
相关资源
最近更新 更多