[小ネタ]monocleでネストしたOption値を扱う
monocleにおけるOptionを含む値の操作のメモです。
はじめに
monocle でOptionを含むcase classの操作をするときの合成をよく忘れるのでそのメモです。
例
ネストしたOptionの内側の変更をする2パターンの例を示します。
- 外側のOptionがないとき、外側の値を作ってから内側の値を操作する
- 外側のOptionがあるときだけ、内側の値を操作する
パターン2はそれぞれの階層におけるlensを作っておいて合成することもできます。
コード
import monocle.macros.GenLens import monocle._ import Monocle._ import cats.implicits._ import monocle.macros.syntax.lens._ object LensExample extends App { final case class Root(node: Option[Node]) final case class Node(name: Option[String]) //Root以下のNodeに名前をセットする。Nodeがなければ空のノードをセットする println(Root(None).lens(_.node).modify(_.getOrElse(Node(None)).lens(_.name).set("New Name".some).some)) //Root以下のNodeに名前をセットする。Nodeがなければセットしない //Nodeがない時 println(Root(None) &|-> GenLens[Root](_.node) ^<-? some ^|-> GenLens[Node](_.name) set "New Name".some) //Nodeがある時 println(Root(Node(None).some) &|-> GenLens[Root](_.node) ^<-? some ^|-> GenLens[Node](_.name) set "New Name".some) //nameを変更 println( Root(Node("name".some).some) &|-> GenLens[Root](_.node) ^<-? some ^|-> GenLens[Node](_.name) modify (_.map( _.toUpperCase))) }
実行結果
//Root以下のNodeに名前をセットする。Nodeがなければ空のノードをセットする Root(Some(Node(Some(New Name)))) //Root以下のNodeに名前をセットする。Nodeがなければセットしない //Nodeがない時 Root(None) //Nodeがある時 Root(Some(Node(Some(New Name)))) //nameを変更 Root(Some(Node(Some(NAME)))) Process finished with exit code 0