At
At is a typeclass that provides an AffineTraversal which allows reading, writing or deleting the value associated with a key in a Map-like containers.
/**
* @tparam S source of a Lens
* @tparam I index of a Lens
* @tparam A target of a Lens
*/
trait At[S, I, A] extends Index[S, I, A] {
def at(i: I): Lens[S, Option[A]]
}
It defines one method at, which given an index of I returns a Lens[S, Option[A]], and inherits Index's
ix method.
Constructing an At
At[S, I, A] is constructed using the at function.
For a given At[S, I, A] it takes two functions as arguments, view: I => S => Option[A] which is a matching function that produces an Option[A] given an index of I and a structure of S, and an index of I,
and set: I => S => Option[A] => S, a function which takes an index of I, a structure of S and an optional focus Option[A] and returns a structure of S.
object At {
def at[S, I, A](view: I => S => Option[A])(set: I => S => Option[A] => S): At[S, I, A]
}
Most of the time we will be using the predefined implicit instances of At, for example an implicit instance of Map. We can use the apply method to summon an instance of Map.
val atMap = At[Map[String, List[String]], String, List[String]]
// import proptics.At
import cats.syntax.option._
import proptics.typeclass.At // some method
// import cats.syntax.option._
import proptics.instances.at._ // summoner of the instance
// import proptics.instances.at._
val seriesMap: Map[String, List[String]] = Map[String, List[String]](
"tt0903747" -> List("True Detective", "Fargo", "Dexter"),
"tt2356777" -> List("Breaking Bad", "Fargo", "Dexter"),
"tt2802850" -> List("Breaking Bad", "True Detective", "Dexter"),
"tt0773262" -> List("Breaking Bad", "True Detective", "Fargo")
)
// seriesMap: Map[String,List[String]] =
// Map(tt0903747 -> List(True Detective, Fargo, Dexter),
// tt2356777 -> List(Breaking Bad, Fargo, Dexter),
// tt2802850 -> List(Breaking Bad, True Detective, Dexter),
// tt0773262 -> List(Breaking Bad, True Detective, Fargo))
// summon of the instance
val atMap: At[Map[String, List[String]], String, List[String]] =
At[Map[String, List[String]], String, List[String]]
// proptics.At[Map[String,List[String]],String,List[String]] =
// proptics.instances.AtInstances$$anon$4@5016596e
val newRecommendation = List("The Mandalorian", "Fargo", "Dexter").some
// newRecommendation: Option[List[String]] = Some(List(The Mandalorian, Fargo, Dexter))
atMap.at("tt0903747").set(newRecommendation.some)(seriesMap)
// res0: Map[String,List[String]] =
// Map(tt0903747 -> List(The Mandalorian, Fargo, Dexter),
// tt2356777 -> List(Breaking Bad, Fargo, Dexter),
// tt2802850 -> List(Breaking Bad, True Detective, Dexter),
// tt0773262 -> List(Breaking Bad, True Detective, Fargo))
// setting to None removes the item from the Map
val newSeriesMap = atMap.at("tt0903747").set(None)(seriesMap)
// newSeriesMap: Map[String,List[String]] =
// Map(tt2356777 -> List(Breaking Bad, Fargo, Dexter),
// tt2802850 -> List(Breaking Bad, True Detective, Dexter),
// tt0773262 -> List(Breaking Bad, True Detective, Fargo))
newSeriesMap.contains("tt0903747")
// res1 : Boolean = false
We can also use the syntax method remove
import proptics.syntax.at._
atMap.remove("tt2356777")(seriesMap)
// res2: Map[String,List[String]] =
// Map(tt0903747 -> List(True Detective, Fargo, Dexter),
// tt2802850 -> List(Breaking Bad, True Detective, Dexter),
// tt0773262 -> List(Breaking Bad, True Detective, Fargo))