æè¿ã¯ Scala å¨ãã®ã©ã¤ãã©ãªãããåå¼·ãã¦ãã¦ãShapelessãCatsã«ã¤ãã¦åå¼·ããäºãå¤ãã ã¨ããã§Monocleã¨ããã©ã¤ãã©ãªãæ°ã«ãªã£ã¦ããã®ã§ãShapelessã®åå¼·ã®æ¯æãã«è»½ã調ã¹ããã¨ã«ããã
Monocleã¨ã¯
Monocleã®å ¬å¼ãã¼ã¸ã«ããã°ã以ä¸ã®ããã«æ¸ããã¦ãã:
Monocle is a Scala library which offers a simple yet powerful API to access and transform immutable data.
ãã端çãªè¡¨ç¾ããã¼ã¸ã®ä¸çªä¸ã«ãæ¸ããã¦ãã:
Access and transform immutable data
Monocleã¯ãã¤ãã¥ã¼ã¿ãã«ãªãã¼ã¿æ§é ã«å¯¾ãã使ãåæã®è¯ãgetter/setterãæä¾ãããã®ãããã
Monocleãã¤ã³ã¹ãã¼ã«ãã
Monocleã®ã¤ã³ã¹ãã¼ã«ã®ããã«ã build.sbt
ã«ä»¥ä¸ã®ãããªä¾åæ§ã追å ãã:
libraryDependencies ++= Seq( "dev.optics" %% "monocle-core" % "3.1.0", "dev.optics" %% "monocle-macro" % "3.1.0", )
å¿ è¦ã«å¿ãã¦ãã¯ãã¢ããã¼ã·ã§ã³ãã¤ã³ã¹ãã¼ã«ã§ããããããã§ã¯ä½¿ããªããã¨ã«ããã
Monocleã®åæ©è½ã®ç´¹ä»
Monocleã¯ããã¤ãã®ä¸»è¦ãªé¨åãæã¡ãããããã«ååãä»ãã¦ããã
- Focus
- Iso
- Lens
- Prism
- Optional
- Traversal
ããããã Focus
ãé¤ãããã®ã¯ Optics
ã¨å¼ã°ãã¦ãã¦ããã¨ãã¨ã¯
Haskell ãããã§çã¾ããæ¦å¿µãããããããã®é¨åãçµã¿åããã¦ã
Monocleã¯ããã§ããgetter/setterã¨ãã¦æ¯ãèãã¨ãããã¨ãããã
ã¾ã㯠Focus
ããæ§åãè¦ã¦ããã
Focus
ããã¥ã¡ã³ãã«ããã°ã Focus
ã¯å
¥éã«æé©ã¨ã®ãã¨ã ã Focus
ã¯ã¤ãã¥ã¼ã¿ãã«ãªãªãã¸ã§ã¯ãã®ãã¡ä¸é¨ã«çµãè¾¼ãã getter/setterãçæãããã¯ãã ã
ã ããFocusã¨ããååãä»ãããã¦ããããã ã
試ãã«ããã ã®ã³ã³ããã®åãããã Box
ãå®ç¾©ã㦠Focus
ã使ã£ã¦ã¿ãã:
import monocle.syntax.all._ case class Box[A](x: A) val box = Box(42) box // => Box[Int](42) box.focus(_.x).replace(84) // => Box[Int](84) box.focus(_.x).modify(_ / 2) // => Box[Int](21)
ããã¾ããªä½¿ãæ¹ãããã£ããã¨ã«ãããcase classã«å¯¾ã㦠.focus()
ãå¼ã³åºãã
ãã®å¯¾è±¡ãé¸æãããã¨ã§ Focus
ãçæããã
ãã¨ã¯ããã«å¯¾ãã¦æä½ãããã¨ã§ã¤ãã¥ã¼ã¿ãã«ãªget/setãå¯è½ãªã®ã ã
ãããã£ã¦æ¬¡ã®ããã«ãæ¸ãã:
val f = box.focus(_.x) f.replace(84) f.modify(_ / 2)
ãã¡ãããå
ã® box
ã«ã¯å½±é¿ãåã¼ããªãã
ã¡ãªã¿ã«Scala 3ã ã¨ããè¤éãªæä½ãå¯è½ã«ãªã£ã¦ããããã ããããã§ã¯å²æã
Iso
Iso
ã¨ã¯ãç°ãªã2ã¤ã®åãç¸äºã«æ
å ±ã失ããã¨ãªãå¤æãããããªOpticsã§ããã
ä¾ãã° List
㨠Vector
ã¨ã®ç¸äºå¤æã ã£ããã case class 㨠Tuple
ã¨ã®ç¸äºå¤æã¨ãã£ãããªãå¤æ§ãª Iso
ãèãããã¨ãã§ããã
import monocle.Iso // Tuple2ã交æããIso def swapIso[A, B] = Iso[(A, B), (B, A)](pair => (pair._2, pair._1))(pair => (pair._2, pair._1)) val pair = (42, "Foo") swapIso.get(pair) // => ("Foo", 42) swapIso.reverseGet(pair) // => å ã«æ»ã // Seq[Seq[A]]ã転置ããIso def transposeIso[A] = Iso[Seq[Seq[A]], Seq[Seq[A]]](s => s.transpose)(s => s.transpose) val lis = Seq(Seq(1,2,3), Seq(4,5,6), Seq(7,8,9)) transposeIso.get(lis) // => Seq(Seq(1, 4, 7), Seq(2, 5, 8), Seq(3, 6, 9)) transposeIso.reverseGet(transposeIso.get(lis)) // => å ã«æ»ã
Iso
ã ãã ã¨ããã¾ãç¹å¾´ãç¡ãæããããâ¦â¦ã
Lens
ãã¦ãOpticsã®ä¸»å½¹ã§ãã Lens
ã®åºçªã ã Lens
ãé©ç¨ãã対象ã¨ãªãå S
ã¨ããã®å
é¨ã«ããå A
ãããã¨ãã S
ã®ä¸ã® A
ãget/setããæ¹æ³ãåãã£ã¦ãããªãã°ãããããçµã¿åãã㦠Lens[S,
A]
ãæ§æãããã¨ãã§ãããä¾ãã°ã Tuple2
ã®å
é è¦ç´ ãæä½ãã Lens
ãæ§æãã¦ã¿ãã:
import monocle.Lens val headLens = Lens[(Int, String), Int](_._1)(a => pair => (a, pair._2)) val pair = (42, "Foo") headLens.get(pair) // => 42 headLens.replace(24)(pair) // => (24, "Foo")
get
㨠replace
ã¨ãå®ç¾©ããããã¨ã«ãããèªåçã« modify
ãæã«å
¥ã:
headLens.modify(_ * 3)(pair) // => (126, "Foo")
ãã®ããã«ãOpticsãã¯ããã¨ããåã¯ã©ã¹ã®é åã¯ãä¸å®ã®æä½ãå®è£ ããã¨èªåçã«ãã便å©ãªæä½ãç¡æã§æã«å ¥ããã¨ã ã
ããæ½è±¡åããã便å©ãªæä½ã¨ãã¦ã modifyF
ã¨ãããã®ãããã
大æåã®Fãç»å ´ãããã¨ããããã£ããåããããã«ããããã¡ã³ã¯ã·ã§ãã«ãªæä½ãå°å
¥ãããã modifyF
ã¯ãæ®éã®é¢æ° A => A
ãåãåããããã« A => F:
cats.Functor
ãåãåããã®ã ã
headLens.modifyF(head => List(head - 1, head, head + 1))(pair) // => List((41, "Foo"), (42, "Foo"), (43, "Foo"))
çµæ§ä¾¿å©ããã ãä»ã«ã Future
ã Functor
ã§ãããã¨ãå©ç¨ãã¦ã
æ§é ã®æ·±ãå ´æã«ããè¦ç´ ãéåæçã«å¤æ´ããã¨ããå¿ç¨ãã§ãããã¨ã«ããã Lens
ãå®ç¾©ããã¦ã㦠Functor
ãå®ç¾©ã§ãã¦ããã°ãã®ãããªä¸æè°ãªæä½ãæã«å
¥ãã®ã¯ããªãä¸æè°ã ã
Lens
å士ã®åæããµãã¼ãããã¦ããã
import monocle.Lens import monocle.macros.GenLens case class Box(x: Int) case class BigBox(box: Box) val boxLens= GenLens[Box](_.x) val bigBoxLens = GenLens[BigBox](_.box) def combinedLens = bigBoxLens andThen boxLens val boxMatryoshka = BigBox(Box(123)) combinedLens.get(boxMatryoshka) // => 123
Prism
ãã¦ã次㯠Prism
ã ã Prism
ã¯ç´åå(Coproductã¨ãSumã¨ãå¼ã°ãã)
ã«å¯¾ãã¦é¸æããä½ç¨ãæã£ã Optics ã ã Lens
ã¯ç´ç©åã«å¯¾ãã¦ãã®è¦ç´ ãé¸æããããã«æ¯ãèã£ãã®ã«å¯¾ãã¦ã Prism
ã¯ãããç´ååã«å¯¾ãã¦è¡ãã
Prism
㯠Lens
ã¨åããããªåãã©ã¡ã¼ã¿ã«ãªã£ã¦ããã ããç´åå S
ãããããã®åã®1ã¤ã« A
ãããã¨ãã S
ãã A
ãåãåºãæä½ã¨ã A
ã S
ã«ããæä½ããããªãã°ã Prism[S, A]
ãæ§æã§ããã
ãã ãã A
ã¯å¤±æããå¯è½æ§ããããããããããã®æä½ã®å®ç¾©ã¯ä»¥ä¸ã®ããã«ãªã:
getOption: S => Option[A] reverseGet: A => S
ä¾ãã°ã Shape
traitã« Circle
㨠Rect
ã¨ãæå±ãã¦ããã¨ãã Circle
ã®åå¾ãåãåºãããã® Prism
ã¯ä»¥ä¸ã®éãã«ãªã:
import monocle.Prism sealed trait Shape case class Circle(r: Int) extends Shape case class Rect(w: Int, h: Int) extends Shape val circleRadiusPrism = Prism.partial[Shape, Int] { case Circle(r) => r }(Circle) val c = Circle(42) val r = Rect(12, 34) circleRadiusPrism.getOption(c) // => Some(42) circleRadiusPrism.getOption(r) // => None
å°ãã¾ã¨ãã¦ã¿ããã
- åSã¨Aã¨ã常ã«ç¸äºå¤æãããã®ã Iso ã§ãã
- åSã¨Aã¨ãç¸äºå¤æãããAã¸ã®å¤æã«å¤±æããããã®ã Prism ã§ãã
- åSãAã«å¤æã§ããSã®ä¸é¨ãAã§ç½®æã§ãããã®ã Lens ã§ãã
ãã㯠https://the.igreque.info/posts/2015-06-09-lens-prism.html ã®åã売ãã
失æããå¯è½æ§ã®ãã Iso
ãæ½è±¡åãããã®ã Prism
ã§ããã¨ãããã
ã¡ãªã¿ã«ã Prism
㯠Lens
ã§ã¯ãªã(ä¼¼ã¦ããããã©)ã
Optional
ãã¦ã Lens
㨠Prism
ã¨ãåä½ããããã㪠Optics ã Optional
ã ã
Optional
ã¯æ¬¡ã®2ã¤ã®é¢æ°ããæ§æã§ãã:
getOption: S => Option[A] replace: A => S => S
確ãã«ã Lens
㨠Prism
ã¨ã®ä¸¡æ¹ã®ç¹å¾´ãåãã¦ããããã«è¦ããã
ããã¥ã¡ã³ãä¸ã§ã¯ããªã¹ãã®å
é è¦ç´ ãæä½ããä¾ãæãããã¦ãã:
import monocle.Optional val head = Optional[List[Int], Int] { case Nil => None case x :: xs => Some(x) }{ a => { case Nil => Nil case x :: xs => a :: xs } }
ããã«ããããªã¹ãã®é·ãã«ããããããå é è¦ç´ ãæä½ãã(å é è¦ç´ ããªãå ´åã¯åã«ç¡è¦ãã) ãããªæä½ãå®ç¾©ã§ããã
ã¡ãªã¿ã«ã Option
ãåä¸ã®è¦ç´ ãæã¤ã³ã³ããã ã¨è§£éãã¦ã
ãããå¤è¦ç´ ã«å±éãããã®ã Traversal
ã (ããã¯å²æ)ã
ã¾ã¨ã
æ§é ã¨æ§é ãå¤æããæ©æ¸¡ãå½¹ã¨ã㦠Monocle ãå½¹ç«ã¡ããã ãä¾ãã° XML / HTML
ãæä½ããã©ã¤ãã©ãªãèãããããã¨ãã«ä½¿ããã®ã§ã¯ãªããã¨æãã
ä¸éçãªæ§é ã®ä¸ã§ã®æä½ãå®ç¾©ãã¦ãããä¸éçãªæ§é ã¸ã®å¤æã¨éå¤æã¨ã( Iso
ãªã©ã§)
çµã¿åããããã¨ã§å¹æçãªè¨è¿°ãã§ããããã«ãªããããããªãã
æè¿å¥ã«åå¼·ãã¦ãã Shapeless ã¨ããã©ã¤ãã©ãªããæ§é ã¨æ§é ã¨ã®é¢ä¿ãåé¡é åã«ãã¦ããã Webç³»ã®ã½ããã¦ã§ã¢ã¨ã³ã¸ãã¢ããã£ã¦ããã¨ç´æ¥æ§é ãæä½ããã¨ããæ©ä¼ã¯ãããªã«ãªãã®ã ãã ä¾ãã° JSON ãã©ãããããã¨ãã HTTP ãããããªãã¨ãããã ã¨ãã£ãã¨ãã«å½¹ç«ããããã¨ãã§ãããããããªãã