Сначала определите способ уменьшения двух Mixture
с помощью инфиксного оператора
implicit class ReduceMixtures(a: Mixture) {
def +(b: Mixture): Mixture =
if (a.ingredient == b.ingredient) Mixture(a.ingredient, a.amount - b.amount)
else a
}
Обратите внимание, что если ingredient
s не совпадает, мы возвращаем a
без изменений. Теперь мы можем реализовать determineWhatsLeft
, используя foldLeft
def determineWhatsLeft(soupRequirements: Seq[Mixture], addedIncredients: Seq[Mixture]): Seq[Mixture] = {
addedIngredients.foldLeft(soupRequirements) { case (acc, next) => acc.map(_ + next) }
}
Используя foldLeft
, порядок не имеет значения, однако если бы порядок soupRequirements
и addedIngredients
всегда был зеркальным, то мы могли бы zip
и map
вот так
def determineWhatsLeft(soupRequirements: Seq[Mixture], addedIncredients: Seq[Mixture]): Seq[Mixture] =
(soupRequirements zip addedIngredients).map { case (a, b) => a + b }
Полугруппа представляется наименее мощной абстракцией, соответствующей требованию
import cats.implicits._
import cats.Semigroup
implicit object mixtureSemigroup extends Semigroup[Mixture] {
def combine(a: Mixture, b: Mixture): Mixture =
if (a.ingredient == b.ingredient) Mixture(a.ingredient, a.amount - b.amount)
else a
}
implicit object seqMixtureSemigroup extends Semigroup[Seq[Mixture]] {
def combine(soupRequirements: Seq[Mixture], addedIncredients: Seq[Mixture]): Seq[Mixture] =
addedIngredients.foldLeft(soupRequirements) { case (acc, next) =>
acc.map(_ |+| next)
}
}
soupRequirements |+| addedIngredients