gpt4 book ai didi

用于收集参数的 Scala 镜头

转载 作者:行者123 更新时间:2023-12-04 18:08:56 25 4
gpt4 key购买 nike

使用镜头更新集合中元素的最佳方法是什么?例如:

case class Ingredient(name: String, quantity: Int)
case class Recipe(val ingredients: List[Ingredient])

如果我想使用镜片来创建一个新配方,并改变单一成分的数量,那么最好的方法是什么?

我尝试过的方法是即时创建一个镜头: Lens[List[Ingredient], Ingredient] .不过这感觉有点笨拙:

case class Recipe(val ingredients: List[Ingredient]) {
import Recipe._
def changeIngredientQuantity(ingredientName: String, newQuantity: Int) = {
val lens = ingredientsLens >=> ingredientLens(ingredientName) >=> Ingredient.quantityLens
lens.set(this, newQuantity)
}
}

object Recipe {
val ingredientsLens = Lens.lensu[Recipe, List[Ingredient]](
(r, i) => r.copy(ingredients = i),
r => r.ingredients
)
def ingredientLens(name: String) = Lens.lensu[List[Ingredient], Ingredient](
(is, i) => is.map (x => if (x.name == name) i else x),
is => is.find(i => i.name == name).get
)
}

case class Ingredient(name: String, quantity: Int)

object Ingredient {
val quantityLens = Lens.lensu[Ingredient, Int](
(i, q) => i.copy(quantity = q),
i => i.quantity
)
}

最佳答案

您不能在给定索引处的 List[T] 和 T 之间创建 Lens,因为 Lens 要求您聚焦的对象始终存在。但是,在查找 List 或另一个集合的情况下,索引处可能没有元素。

但是,您可以使用 Traversal,这是一种聚焦 0 到多个元素的 Lens。与 Monocle ,您将使用 index 函数创建从列表到给定索引处的元素的遍历:

import monocle.SimpleLens
import monocle.syntax.lens._ // to use |-> and |->> instead of composeLens, composeTraversal
import monocle.functions.Index._ // to use index Traversal

// monocle also provides a macro to simplify lens creation
val ingredientsLens = SimpleLens[Recipe, List[Ingredient]](_.ingredients, (recipe, newIngredients) => recipe.copy(ingredients = newIngredients))
val quantityLens = SimpleLens[Ingredient, Int](_.quantity , (ingredient, newQuantity) => ingredient.copy(quantity = newQuantity))

val applePie = Receipe(List(Ingredient("apple", 3), Ingredient("egg", 2), ...))


applePie |-> ingredientsLens |->> index(0) headOption // Some(Ingredient("apple", 3))
applePie |-> ingredientsLens |->> index(999) headOption // None
applePie |-> ingredientsLens |->> index(0) |->> quantityLens headOption // 3
applePie |-> ingredientsLens |->> index(0) |->> quantityLens set 5
// Receipe(List(Ingredient("apple", 5), Ingredient("egg", 2), ...))

关于用于收集参数的 Scala 镜头,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19444742/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com