IndexedGetter
An IndexedGetter describes how to retrieve a single value with its index. It is similar to a IndexedFold, but it
focuses on a single pair of element and index. An IndexedGetter[I, S, A] is just any function S => (A, I), everything you can do with a function, you can do with a IndexedGetter.
IndexedGetter internal encoding
Polymorphic IndexedGetter
IndexedGetter_[I, S, T, A, B]
IndexedGetter_[I, S, T, A, B] is a function
Indexed[Forget[(A, I), *, *], I, A, B] => Forget[(A, I), S, T]
Forget is a data type shaped like a profunctor, which forgets its last type parameter.
/**
* @tparam I the index of an IndexedGetter_
* @tparam S the source of a IndexedGetter_
* @tparam T the modified source of a IndexedGetter_
* @tparam A the focus of a IndexedGetter_
* @tparam B the modified focus of anIndexedGetter_
*/
abstract class IndexedGetter_[I, S, T, A, B] {
def apply(indexed: Indexed[Forget[(A, I), *, *], I, A, B]): Forget[(A, I), S, T]
}
Although IndexedGetter_[I, S, T, A, B] is read-only, and cannot change its foci, it has a definition of Polymorphic IndexedGetter, serving as
a base type from which a Monomorphic IndexedGetter can be obtained.
Monomorphic IndexedGetter
IndexedGetter[I, S, A]
IndexedGetter[I, S, A] is a type alias for IndexedGetter_[I, S, S, A, A], which has the same type of focus A, thus preserving the same type of structure S.
type IndexedGetter[I, S, A] = IndexedGetter_[I, S, S, A, A]
Since IndexedGetter is read-only, IndexedGetter[I, S, A] is isomorphic to IndexedGetter_[I, S, T, A, B].
IndexedGetter_[I, S, T, A, B] takes Indexed[Forget[(A, I), *, *], I, A, B] and returns Forget[(A, I), S, T].
Indexed[Forget[(A, I), *, *], I, A, B] wraps a value of Forget[(A, I), (A, I), B], so the representation of the apply method can be simplified to:
Forget[(A, I), (A, I), B] => Forget[(A, I), S, T]
Forget[(A, I), (A, I), B] wraps a function (A, I) => (A, I) and forgets its last type parameter B.
Forget[(A, I), S, T] wraps a function S => (A, I) and forgets its last type parameter T,
so the representation of can be even more simplified to:
((A, I) => (A, I)) => S => (A, I)
Let's compare it to IndexedGetter_[I, S, S, A, A] which is equivalent to IndexedGetter[I, S, A].
def IndexedGetter[I, S, A]: IndexedGetter[I, S, A] = new IndexedGetter_[I, S, S, A, A] {
def apply(indexed: Indexed[Forget[(A, I), *, *], I, A, A]): Forget[(A, I), S, S]
}
IndexedGetter_[I, S, S, A, A] takes Forget[(A, I), *, *], I, A, A] and returns Forget[(A, I), S, S].
Indexed[Forget[(A, I), *, *], I, A, A] wraps a value of Forget[(A, I), (A, I), A], so the representation of the apply method can be simplified to:
Forget[(A, I), (A, I), A] => Forget[(A, I), S, S]
Forget[(A, I), (A, I), A] wraps a function (A, I) => (A, I) and forgets its last type parameter A.
Forget[(A, I), S, S] wraps a function S => (A, I) and forgets its last type parameter S,
so the representation of can be even more simplified to:
((A, I) => (A, I)) => S => (A, I)
Constructing IndexedGetters
IndexedGetter_[I, S, T, A, B] is constructed using the IndexedGetter_[I, S, T, A, B]#apply function.
For a given IndexedGetter_[I, S, T, A, B] it takes a function as argument S => (A, I).
object IndexedGetter_ {
def apply[I, S, T, A, B](get: S => (A, I)): IndexedGetter[I, S, T, A, B]
}
IndexedGetter[I, S, A] is constructed using the IndexedGetter[I, S, T, A, B]#apply function.
For a given IndexedGetter[I, S, A] it takes a function as argument S => (A, I).
object IndexedGetter {
def apply[I, S, A](get: S => (A, I)): IndexedGetter[I, S, A]
}
Consider a Map[String, List[String]] of series recommendations, and we want to get
an entry by a specific index.
import proptics.IndexedGetter
// import proptics.IndexedGetter
import cats.instances.option._ // instance of Eq[Option]
// import cats.instances.option._
import cats.syntax.eq._ // triple equals (===)
// import cats.syntax.eq._
import cats.syntax.option._ // some function
// import cats.syntax.option._
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))
val indexedGetter: IndexedGetter[String, Map[String, List[String]], Option[List[String]]] =
IndexedGetter[String, Map[String, List[String]], Option[List[String]]] { map =>
(map.get("tt0903747"), "tt0903747")
}
// indexedGetter: proptics.IndexedGetter[String,Map[String,List[String]],Option[List[String]]] =
// proptics.IndexedGetter_$$anon$14@33ddee76
Common functions of a IndexedGetter
view
indexedGetter.view(seriesMap)
// res0: (Option[List[String]], String) = (Some(List(True Detective, Fargo, Dexter)),tt0903747)
exists
indexedGetter.exists(_._2 === "tt0903747")(seriesMap)
// res1: Boolean = true
contains
val series = List("Breaking Bad", "True Detective", "Fargo")
// series: List[String] = List(Breaking Bad, True Detective, Fargo)
indexedGetter.contains((series.some, "tt0903747"))(seriesMap)
// res2: Boolean = false
find
indexedGetter.find(_._2 === "tt0903747")(seriesMap)
// res4: Option[(Option[List[String]], String)] = Some((Some(List(True Detective, Fargo, Dexter)),tt0903747))
Laws
Since a IndexedGetter cannot be used to write back there are no Lens laws that apply to it.