Skip to content

Commit

Permalink
optics
Browse files Browse the repository at this point in the history
  • Loading branch information
rpiaggio committed May 30, 2024
1 parent 95dc0db commit 80c2053
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 0 deletions.
1 change: 1 addition & 0 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ lazy val model =
Settings.Libraries.CatsTestkit.value ++
Settings.Libraries.Circe.value ++
Settings.Libraries.DisciplineMUnit.value ++
Settings.Libraries.Monocle.value ++
Settings.Libraries.MUnit.value
)

Expand Down
23 changes: 23 additions & 0 deletions model/src/main/scala/clue/data/InputOptics.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright (c) 2016-2023 Association of Universities for Research in Astronomy, Inc. (AURA)
// For license information see LICENSE or https://opensource.org/licenses/BSD-3-Clause

package clue.data

import monocle.PPrism
import monocle.Prism

trait InputOptics {
final def pAssign[A, B]: PPrism[Input[A], Input[B], A, B] =
PPrism[Input[A], Input[B], A, B](_.toOption.map(Right(_)).getOrElse(Left(Ignore)))(Assign.apply)

final def assign[A]: Prism[Input[A], A] =
pAssign[A, A]

final def ignore[A]: Prism[Input[A], Unit] =
Prism[Input[A], Unit] { case Ignore => Some(()); case _ => None }(_ => Ignore)

final def unassign[A]: Prism[Input[A], Unit] =
Prism[Input[A], Unit] { case Unassign => Some(()); case _ => None }(_ => Unassign)
}

object optics extends InputOptics
17 changes: 17 additions & 0 deletions model/src/main/scala/clue/data/syntax/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@

package clue.data

import monocle.PLens
import monocle.POptional
import clue.data.optics

package object syntax {
implicit final class AnyToInputOps[A](private val a: A) extends AnyVal {
def assign: Input[A] = Assign(a)
Expand All @@ -12,4 +16,17 @@ package object syntax {
def orIgnore: Input[A] = Input.orIgnore(a)
def orUnassign: Input[A] = Input.orUnassign(a)
}

implicit final class LensToLensOps[S, T, A, B](private val lens: PLens[S, T, A, B])
extends AnyVal {
// Copied verbatim from monocle, which has it as a private member
private def adapt[A1, B1](implicit evA: A =:= A1, evB: B =:= B1): PLens[S, T, A1, B1] =
evB.substituteCo[PLens[S, T, A1, *]](evA.substituteCo[PLens[S, T, *, B]](lens))

def assign[A1, B1](implicit
ev1: A =:= Input[A1],
ev2: B =:= Input[B1]
): POptional[S, T, A1, B1] =
adapt[Input[A1], Input[B1]].andThen(optics.pAssign[A1, B1])
}
}

0 comments on commit 80c2053

Please sign in to comment.