ocular/optics

Common optics for Gleam standard library types.

This module provides pre-built optics for working with:

Values

pub fn dict_key(
  key: k,
) -> types.Optional(dict.Dict(k, v), dict.Dict(k, v), v, v)

An optional that focuses on a specific key in a dictionary. Returns Ok(value) if the key exists, Error(Nil) otherwise.

Example

let d = dict.from_list([#("name", "Alice"), #("age", "30")])
let name_opt = dict_key("name")

ocular.get_opt(d, name_opt)  // Ok("Alice")
ocular.set_opt(d, name_opt, "Bob")  // dict with "name" -> "Bob"
pub fn dict_key_with_default(
  key: k,
  default: v,
) -> types.Lens(dict.Dict(k, v), dict.Dict(k, v), v, v)

An optional that focuses on a key, with a default value if missing. Unlike dict_key, this always “succeeds” for gets (returns the value or default).

Example

let d = dict.from_list([#("name", "Alice")])
let name_lens = dict_key_with_default("name", "Unknown")
let age_lens = dict_key_with_default("age", "0")

ocular.get(d, name_lens)  // "Alice"
ocular.get(d, age_lens)   // "0"
ocular.set(d, age_lens, "30")  // dict with "name" -> "Alice", "age" -> "30"
pub fn error() -> types.Prism(Result(a, e), Result(a, f), e, f)

A prism that focuses on the Error variant of a Result.

Example

let x: Result(Nil, String) = Error("failure")
ocular.preview(x, error())  // Ok("failure") // Notice how the focus shifts to the error value!

ocular.review(error(), "failure")  // Error("failure")
pub fn first() -> types.Lens(#(a, b), #(c, b), a, c)

A lens that focuses on the first element of a 2-tuple.

Example

let pair = #("hello", 42)
ocular.get(pair, first())  // "hello"
ocular.set(pair, first(), "world")  // #("world", 42)
pub fn first3() -> types.Lens(#(a, b, c), #(d, b, c), a, d)

A lens that focuses on the first element of a 3-tuple.

pub fn id() -> types.Lens(a, b, a, b)

The identity lens. Focuses on the whole structure.

This is the neutral element for lens composition:

  • id |> compose.lens(other) = other
  • other |> compose.lens(id) = other

Example

let x = "hello"
ocular.get(x, id())  // "hello"
ocular.set(x, id(), "world")  // "world"
ocular.modify(x, id(), string.uppercase)  // "HELLO"
pub fn list_head(
  default: a,
) -> types.Lens(List(a), List(a), a, a)

A lens that focuses on the first element of a list. Returns the default value if the list is empty.

Example

let items = ["a", "b", "c"]
let head = list_head("default")

ocular.get(items, head)  // "a"
ocular.get([], head)     // "default"
ocular.set(items, head, "A")  // ["A", "b", "c"]
pub fn list_index(
  index: Int,
) -> types.Optional(List(a), List(a), a, a)

An optional that focuses on a specific index in a list. Returns Ok(value) if the index is valid, Error(Nil) otherwise.

Example

let items = ["a", "b", "c"]
let second = list_index(1)

ocular.get_opt(items, second)  // Ok("b")
ocular.set_opt(items, second, "B")  // ["a", "B", "c"]
pub fn list_tail() -> types.Lens(
  List(a),
  List(a),
  List(a),
  List(a),
)

A lens that focuses on the tail of a list (everything after the first element).

Example

let items = ["a", "b", "c"]
let tail = list_tail()

ocular.get(items, tail)  // ["b", "c"]
ocular.set(items, tail, ["x"])  // ["a", "x"]
pub fn list_traversal() -> types.Traversal(List(a), List(b), a, b)

A traversal that focuses on all elements of a list.

Example

let items = [1, 2, 3]
let all = list_traversal()

ocular.get_all(items, all)  // [1, 2, 3]
ocular.modify_all(items, all, fn(x) { x * 2 })  // [2, 4, 6]
pub fn none() -> types.Prism(
  option.Option(a),
  option.Option(a),
  Nil,
  Nil,
)

A prism that focuses on the None variant of an Option. This is mostly useful for checking if something is None or constructing None.

Example

let x: Maybe(String) = None
ocular.preview(x, none())  // Ok(Nil)

let y: Maybe(String) = Some("hello")
ocular.preview(y, none())  // Error(Nil)

ocular.review(none(), Nil) // None
pub fn ok() -> types.Prism(Result(a, e), Result(b, e), a, b)

A prism that focuses on the Ok variant of a Result.

Example

let x: Result(String, Nil) = Ok("success")
ocular.preview(x, ok())  // Ok("success")

ocular.review(ok(), "success")  // Ok("success")
pub fn second() -> types.Lens(#(a, b), #(a, c), b, c)

A lens that focuses on the second element of a 2-tuple.

Example

let pair = #("hello", 42)
ocular.get(pair, second())  // 42
ocular.set(pair, second(), 100)  // #("hello", 100)
pub fn second3() -> types.Lens(#(a, b, c), #(a, d, c), b, d)

A lens that focuses on the second element of a 3-tuple.

pub fn some() -> types.Prism(
  option.Option(a),
  option.Option(b),
  a,
  b,
)

A prism that focuses on the Some variant of an Option.

Example

let x: Maybe(String) = Some("hello")
ocular.preview(some_prism(), x)  // Ok("hello")

let y: Maybe(String) = None
ocular.preview(some_prism(), y)  // Error(Nil)

ocular.review(some_prism(), "world")  // Some("world")
pub fn some_with_default(
  default: a,
) -> types.Lens(option.Option(a), option.Option(a), a, a)

An optional that unwraps an Option, with a default for the “get” operation. Unlike some_prism, this returns the default when getting from None.

Example

let opt_str = some_with_default("default")

ocular.get(Some("hello"), opt_str)  // "hello"
ocular.get(None, opt_str)           // "default"
ocular.set(None, opt_str, "new")    // Some("new")
pub fn third3() -> types.Lens(#(a, b, c), #(a, b, d), c, d)

A lens that focuses on the third element of a 3-tuple.

Search Document