Iso
An Iso[A, B] is to and from that are inverses. import conduit.Iso.* brings imap /
xmap on Lens: view an Int field as a String (or any other type) without storing the
viewed type in the model.
Lawfulness is on you. If from(to(a)) != a, lens laws on the derived lens fail in the places
the iso loses information.
imap / xmap
import conduit.Iso.*
val intToStr = Iso[Int, String](_.toString, _.toInt)
val asStr = Optics[Box](_.n).imap(intToStr)
// xmap(to, from) is imap(Iso(to, from))
Mermoid.diagram(round){
val box = Box(42)
(asStr.get(box), asStr.set(box, "100").n)
}(42,100)Live: store Int, show String
The model is Box(n: Int). Buttons write through the iso (SetStr) or the raw Int lens
(Inc). Both stay in sync.
for
(_, ctx) <- DocsRuntime.live(Box(7))(handler)
n <- ctx.squawk(_.n)
yield E.div(
E.p("stored Int: ", E.strong(n.map(_.toString))),
E.button(Events.onClick(_ => ctx(BoxOp.Inc)), "Inc"),
E.button(Events.onClick(_ => ctx(BoxOp.SetStr("0"))), "Set 0"),
E.button(Events.onClick(_ => ctx(BoxOp.SetStr("42"))), "Set 42"),
)stored Int: 7
for
c <- Conduit(Box(7))(handler)
_ <- c(BoxOp.SetStr("10"), BoxOp.Inc)
_ <- c.run()
s <- c.currentModel
yield (s.n, asStr.get(s))(11,11)reverse
iso.reverse swaps to / from. Iso.id[A] is the identity. Compose isos yourself if you
need a pipeline; Conduit only ships imap on one lens.
Mermoid.diagramInteractive(round, initialWidth = 480)viewport 480px