javascript - 在 Ramda 中做一些无积分的事情

标签 javascript ramda.js pointfree

我现在正在学习 JS 库 Ramda。似乎有一种我无法正确解决的模式。例如我有这个代码。

const filterPayments = filter => payments =>
  r.filter(
    r.allPass([
      typePred(filter),
      amountPred(filter),
      accountPred(filter),
      currencyPred(filter)
    ]),
    payments
  );

现在看来,我距离使其自由化已经不远了。我似乎找不到正确的方法。

此外,我在制作像这样的完全功能性且无点的逻辑函数时遇到了麻烦:

const amountPred = filter => p =>
  r.and(p.betrag >= filter.amount.min, p.betrag <= filter.amount.max);

也许有人可以指出我正确的方向或提供一些指导?

最佳答案

我提供的指导是坚持你目前拥有的:)

我可以向您展示一个示例,说明您所拥有的内容的无点翻译可能是什么样子,尽管生成的代码读起来非常糟糕,而且实际上只适合进行心理体操。

首先,付款出现在函数表达式两侧的最终位置,因此我们可以简单地将其删除。

const filterPayments = filter =>
  R.filter(
    R.allPass([
      typePred(filter),
      amountPred(filter),
      accountPred(filter),
      currencyPred(filter)
    ]));

接下来我们可以处理传递给R.allPass的函数列表

R.allPass(R.map(p => p(filter), [typePred, amountPred, accountPred, currencyPred]))

现在我们可以通过翻转 R.map 将其推向末尾来开始删除 filter 参数。

R.allPass(R.flip(R.map)([typePred, amountPred, accountPred, currencyPred])(p => p(filter))

现在让我们创建filter并将参数传递给p => p(filter),而不是关闭它,使其:

R.allPass(R.flip(R.map)
  ([typePred, amountPred, accountPred, currencyPred])
  (R.applyTo(filter)))

现在开始形成像 h(g(f(a))) 这样的形状,我们可以使用 R.pipe 将其转换为无点,R.composeR.o

const filterPayments = R.compose(
  R.filter,
  R.allPass,
  R.flip(R.map)([typePred, amountPred__, accountPred, currencyPred]),
  R.unary(R.applyTo) // R.unary is needed here to tell Ramda only to expect the first argument in this composition
)

这为我们提供了一个现在应该相当于无积分形式的 filterPayments 的函数。

您的 amountPred 示例变得更加复杂,我想您之后会同意您已经拥有的是两者之间更好的选择。

同样,我们首先尝试将参数插入表达式每一侧的末尾:

filter => p =>
  both(
    x => x >= filter.amount.min,
    x => x <= filter.amount.max
  )(p.betrag)

然后我们可以删除p:

filter => R.o(
  both(
    x => x >= filter.amount.min,
    x => x <= filter.amount.max
  ),
  prop('betrag'))

传递给both的函数也可以交换:

filter => R.o(
  both(
    R.flip(R.gte)(filter.amount.min),
    R.flip(R.lte)(filter.amount.max)
  ),
  prop('betrag'))

现在要解决filter问题,我们可以使用R.converge将相同的参数传递给多个函数,然后将每个函数的结果组合在一起。

filter => R.o(
  R.converge(both, [
    f => R.flip(R.gte)(R.path(['amount', 'min'], f),
    f => R.flip(R.lte)(R.path(['amount', 'max'], f)
  ])(filter),
  prop('betrag'))

现在 f 位于结束位置,因此可以通过组合删除它:

filter => R.o(
  R.converge(both, [
    R.o(R.flip(R.gte), R.path(['amount', 'min'])),
    R.o(R.flip(R.lte), R.path(['amount', 'max']))
  ])(filter),
  prop('betrag'))

filter 放到最后会变得非常困惑,涉及翻转组合函数。

filter => R.o(
  R.flip(R.o)(R.prop('betrag')),
  R.converge(both, [
    R.o(R.flip(R.gte), R.path(['amount', 'min'])),
    R.o(R.flip(R.lte), R.path(['amount', 'max']))
  ])
)(filter)

最后...

const amountPred = R.o(
  R.flip(R.o)(R.prop('betrag')),
  R.converge(both, [
    R.o(R.flip(R.gte), R.path(['amount', 'min'])),
    R.o(R.flip(R.lte), R.path(['amount', 'max']))
  ])
)

...将其与您的原件进行比较,我知道我更喜欢阅读哪一个:

const amountPred = filter => p =>
  p.betrag >= filter.amount.min && p.betrag <= filter.amount.max

关于javascript - 在 Ramda 中做一些无积分的事情,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51104942/

相关文章:

javascript - 按下一个 id 对双向链表进行排序 Ramda.js

haskell - 为什么这个函数的pointfree版本看起来像这样?

javascript - jQuery:hasClass 部分匹配

javascript - 使用 javascript 从 ASPX 代码隐藏页面访问类

javascript - 为什么这个 html 不使用 jQuery 更新?

pointfree - 具有多个函数参数的无点表示法

haskell - Haskell 中的 Pointfree 风格编程

javascript - 使用 Javascript 根据 URL 哈希设置所选选项

javascript - 一次更新设置多个 Ramda 镜头

javascript - Ramda如何将参数传递给高阶函数?