【问题标题】:cats and function compositions猫和功能组合物
【发布时间】:2020-06-23 11:27:15
【问题描述】:

我有数据类型:

import cats.Monoid
import cats.implicits._

object Domain {
  case class Money(amount: Double) extends AnyVal {}

  implicit val moneyMonoid = new Monoid[Money] {
    override def combine(a: Money, b: Money): Money = Money(a.amount + b.amount)
    override def empty: Money                       = Money(0)
  }

  case class Operation(account: Account, amount: Money) extends AnyRef
  type Operations = List[Operation]
}

我想实现totalAmountCalculation之类的函数组合

val calcTotalAmount = map(x => x.amount) >>> combineAll

为此我写了一些代码:

def map[A, B](F: A => B): List[A] => List[B] = (m: List[A]) => m.map(F) 
val combineAll      = moneyMonoid.combineAll _

val calcTotalAmount = map[Operation, Money](x => x.amount) >>> combineAll

我可以使用哪些猫特性来避免编写 Monad 包装器以在函数组合中使用它?

我想看到我的代码:

map(x => x + 1) >>>
filter(x < 100) >>> 
fold(1)((a,b) => a+b))

【问题讨论】:

  • 我可以用来避免写 Monad 包装器 - 你的意思是Monoid
  • 我的意思是:对于 Monoid,我有一些方法,例如 combine combineAll,对于 Monad,我有 flatMap, map,对于可折叠的“foldLeft foldRight”。我怎样才能在作文中轻松使用咖喱?
  • Monad 的组成方式与函数的组成方式不同。
  • 灵感来自 ramda.js。
  • 好用的东西val filterOdd= filter(x =&gt; x %2); val sumOdd = filterOdd &gt;&gt; combineAll

标签: scala scala-cats


【解决方案1】:

如果我正确理解了您的问题,您希望避免使用包装器 Amount 并且必须在函数定义中的任何地方使用 x =&gt; x.amount

有几种方法可以解决这个问题。第一种是使用类型别名,就像您对操作所做的那样。这自然会为您提供默认的Monoid[Int],其中0 对应zero,另外还有combine

allMoney
 .map(_ + 1.0)
 .filter(_ > 3.0)
 .foldLeft(1.0)(_ + _)

// 13.0

allMoney.combineAll

// 12.0

另一种选择是使用newtype 库,它使用案例类可以产生类似的效果:

@newsubtype case class Money(amount: Double)

allMoney
  .map(_ + 1.0)
  .filter(_ > 3.0)
  .foldLeft(1.0)(_ + _)

// 13.0

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-27
    • 2016-04-04
    • 2021-03-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多