A \"lens\" and a \"partial lens\" seem rather similar in name and in concept. How do they differ? In what circumstances do I need to use one or the other?
Tagging Scala
Below are the scaladocs for Scalaz's LensFamily and PLensFamily, with emphasis added on the diffs.
Lens:
A Lens Family, offering a purely functional means to access and retrieve a field transitioning from type
B1to typeB2in a record simultaneously transitioning from typeA1to typeA2.scalaz.Lensis a convenient alias for whenA1 =:= A2, andB1 =:= B2.The term "field" should not be interpreted restrictively to mean a member of a class. For example, a lens family can address membership of a
Set.
Partial lens:
Partial Lens Families, offering a purely functional means to access and retrieve an optional field transitioning from type
B1to typeB2in a record that is simultaneously transitioning from typeA1to typeA2.scalaz.PLensis a convenient alias for whenA1 =:= A2, andB1 =:= B2.The term "field" should not be interpreted restrictively to mean a member of a class. For example, a partial lens family can address the nth element of a
List.
For those unfamiliar with scalaz, we should point out the symbolic type aliases:
type @>[A, B] = Lens[A, B]
type @?>[A, B] = PLens[A, B]
In infix notation, this means the type of a lens that retrieves a field of type B from a record of type A is expressed as A @> B, and a partial lens as A @?> B.
Argonaut (a JSON library) provides a lot of examples of partial lenses, because the schemaless nature of JSON means that attempting to retrieve something from an arbitrary JSON value always has the possibility of failure. Here are a few examples of lens-constructing functions from Argonaut:
def jArrayPL: Json @?> JsonArray — Retrieves a value only if the JSON value is an arraydef jStringPL: Json @?> JsonString — Retrieves a value only if the JSON value is a stringdef jsonObjectPL(f: JsonField): JsonObject @?> Json — Retrieves a value only if the JSON object has the field fdef jsonArrayPL(n: Int): JsonArray @?> Json — Retrieves a value only if the JSON array has an element at index n