Scala 在使用组合光学元件构建的路径中定义可选值
我使用默认值创建了嵌套案例类的结构:Scala 在使用组合光学元件构建的路径中定义可选值,scala,lenses,monocle-scala,Scala,Lenses,Monocle Scala,我使用默认值创建了嵌套案例类的结构: case class Alpha(text: String = "content") case class Beta(alpha: Alpha = Alpha()) case class Gamma(beta: Option[Beta] = None) 我想用默认值创建整个东西,然后使用Monocle修改需要非默认的元素 使用isos很容易。我可以使用composition指定导航,然后使用set修改内部元素: object Beta { val al
case class Alpha(text: String = "content")
case class Beta(alpha: Alpha = Alpha())
case class Gamma(beta: Option[Beta] = None)
我想用默认值创建整个东西,然后使用Monocle修改需要非默认的元素
使用isos很容易。我可以使用composition指定导航,然后使用set修改内部元素:
object Beta {
val alphaI: Iso[Beta, Alpha] = GenIso[Beta, Alpha]
}
object Alpha {
val textI: Iso[Alpha, String] = GenIso[Alpha, String]
}
(Beta.alphaI composeIso Alpha.textI).set("foo")(Beta()) shouldBe Beta(Alpha("foo"))
不幸的是,使用prims时,它似乎没有那么优雅,因为set
/modify
只会在定义了导航过程中的所有选项时修改内部元素(Some(…)
)
到目前为止,我想到的最好的方法是使用合成光学设置路径的每个可选元素,然后使用合成光学设置我们感兴趣的元素
(Gamma.betaI.set(Some(Beta())) andThen navigateToText.set("foo")) (Gamma()) shouldBe Gamma(Some(Beta(Alpha("foo"))))
理想情况下,我希望合成的每个构建块将可选值设置为Some(defaultValue)
,如果它们最初是None
。显然,需要定义构建块,包括路径步骤的适当默认值。
有什么建议吗
完整代码,包括导入:您可以使用
Prism中的下面的,例如光学组件中匹配的类型:
import monocle.macros.GenIso
import scalaz.std.option._
case class Alpha(text: String = "content")
case class Beta(alpha: Alpha = Alpha())
case class Gamma(beta: Option[Beta] = None)
val navigateToText = GenIso[Gamma, Option[Beta]] composePrism
GenIso[Beta, Alpha].asPrism.below[Option] composePrism
GenIso[Alpha, String].asPrism.below[Option]
navigateToText.set(Some("foo"))(Gamma(None)) // Gamma(Some(Beta(Alpha(foo))))
navigateToText.set(Some("foo"))(Gamma(Some(Beta(Alpha("bar"))))) // Gamma(Some(Beta(Alpha(foo))))
太好了,效果很好!当有可选孩子的父母有其他孩子时,它也适用于镜头。(我无法在这里正确格式化代码,但我尝试了使用镜头的合成)不幸的是,我无法使用monocle 2.1.0
和scalaz core 7.3.3
编译此代码<代码>未找到:值
和找不到选项
的遍历实例是错误消息
import monocle.macros.GenIso
import scalaz.std.option._
case class Alpha(text: String = "content")
case class Beta(alpha: Alpha = Alpha())
case class Gamma(beta: Option[Beta] = None)
val navigateToText = GenIso[Gamma, Option[Beta]] composePrism
GenIso[Beta, Alpha].asPrism.below[Option] composePrism
GenIso[Alpha, String].asPrism.below[Option]
navigateToText.set(Some("foo"))(Gamma(None)) // Gamma(Some(Beta(Alpha(foo))))
navigateToText.set(Some("foo"))(Gamma(Some(Beta(Alpha("bar"))))) // Gamma(Some(Beta(Alpha(foo))))