Lens es una biblioteca para Haskell que proporciona lentes, isomorfismos, pliegues, recorridos, captadores y definidores, lo que expone una interfaz uniforme para consultar y manipular estructuras arbitrarias, no como los conceptos de acceso y mutación de Java.
Las lentes (y otras ópticas) nos permiten separarnos describiendo cómo queremos acceder a algunos datos de lo que queremos hacer con ellos. Es importante distinguir entre la noción abstracta de una lente y la implementación concreta. La comprensión abstracta hace que la programación con lens
sea mucho más fácil a largo plazo. Hay muchas representaciones isomorfas de lentes, por lo que para esta discusión evitaremos cualquier discusión de implementación concreta y, en cambio, ofreceremos una visión general de alto nivel de los conceptos.
Un concepto importante en la comprensión abstracta es la noción de enfoque . Las ópticas importantes se centran en una parte específica de una estructura de datos más grande sin olvidar el contexto más amplio. Por ejemplo, la lente _1
enfoca en el primer elemento de una tupla pero no se olvida de lo que había en el segundo campo.
Una vez que tenemos el enfoque, podemos hablar sobre qué operaciones se nos permite realizar con una lente. Dado un Lens sa
que cuando se da un tipo de datos de tipo s
se centra en un determinado a
, podemos ya sea
a
olvidando el contexto adicional o a
proporcionando un nuevo valor Estos corresponden a las conocidas operaciones de get
y set
que normalmente se utilizan para caracterizar una lente.
Podemos hablar de otras ópticas de manera similar.
Óptico | Se centra en... |
---|---|
Lente | Una parte de un producto |
Prisma | Una parte de una suma |
Travesía | Cero o más partes de una estructura de datos |
Isomorfismo | ... |
Cada óptica se enfoca de una manera diferente, como tal, dependiendo de qué tipo de óptica tengamos podemos realizar diferentes operaciones.
Además, podemos componer cualquiera de las dos ópticas que hemos discutido hasta ahora para especificar accesos de datos complejos. Los cuatro tipos de ópticas que hemos discutido forman una red, el resultado de componer dos ópticas juntas es su límite superior.
Por ejemplo, si componemos juntos una lente y un prisma, obtenemos un recorrido transversal. La razón de esto es que por su composición (vertical), primero nos enfocamos en una parte de un producto y luego en una parte de una suma. El resultado es una óptica que se centra precisamente en cero o en una parte de nuestros datos, que es un caso especial de un recorrido. (Esto a veces también se llama un recorrido afín).
La razón de la popularidad en Haskell es que hay una representación muy breve de la óptica. Todas las ópticas son solo funciones de una cierta forma que se pueden componer juntas utilizando la función de composición. Esto lleva a una incrustación muy ligera que facilita la integración de la óptica en sus programas. Además de esto, debido a los detalles de la codificación, la composición de la función también calcula automáticamente el límite superior de las dos ópticas que componemos. Esto significa que podemos reutilizar los mismos combinadores para diferentes ópticas sin una conversión explícita.