The Optics DSL has special support for optics that refer to elements in a collection.
Every can be used to focus into a structure S and see all its foci A. Here, we focus into all Employees in the Employees.
@optics data class Employees(val employees: List<Employee>) {
  companion object
}
import arrow.optics.Every
val jane = Employee("Jane Doe", Company("Kategory", Address("Functional city", Street(42, "lambda street"))))
val employees = Employees(listOf(john, jane))
Employees.employees.every(Every.list<Employee>()).company.address.street.name.modify(employees, String::capitalize)
If you are in the scope of Each, you don’t need to specify the instance.
Every.list<Employee>().run {
  Employees.employees.every.company.address.street.name.modify(employees, String::capitalize)
}
At can be used to focus in A at a given index I for a given structure S.
@optics data class Db(val content: Map<Int, String>) {
  companion object
}
Here we focus into the value of a given key in MapK.
import arrow.optics.typeclasses.At
val db = Db(mapOf(
  1 to "one",
  2 to "two",
  3 to "three"
))
Db.content.at(At.map(), 2).some.modify(db, String::reversed)
If you are in the scope of At, you don’t need to specify the instance.
At.map<Int, String>().run {
  Db.content.at(2).some.modify(db, String::reversed)
}
Index can be used to operate on a structure S that can index A by an index I (i.e., a List<Employee> by its index position or a Map<K, V> by its keys K).
import arrow.optics.typeclasses.Index
val updatedJohn = Employees.employees.index(Index.list(), 0).company.address.street.name.modify(employees, String::capitalize)
updatedJohn
In the scope of Index, you don’t need to specify the instance, so we can enable operator fun get syntax.
Index.list<Employee>().run {
  Employees.employees[0].company.address.street.name.getOrNull(updatedJohn)
}
Since Index returns an Optional, index and [] are safe operations.
Index.list<Employee>().run {
  Employees.employees[2].company.address.street.name.getOrNull(employees)
}
Do you like Arrow?
✖