Optics DSL for Collections

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)

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 {

Since Index returns an Optional, index and [] are safe operations.

Index.list<Employee>().run {

Do you like Arrow?

Arrow Org