鏡片

什麼是鏡頭?

鏡頭(和其他光學)讓我們分開描述如何,我們想從訪問某些資料是什麼,我們想用它做。區分鏡頭的抽象概念和具體實現是很重要的。從長遠來看,抽象地理解使用 lens 進行程式設計變得更容易。鏡頭有許多同構表示,因此在本次討論中,我們將避免任何具體的實現討論,而是對概念進行高階概述。

調焦

抽象理解的一個重要概念是聚焦的概念。重要的光學器件專注於更大資料結構的特定部分,而不會忘記更大的背景。例如,鏡頭 _1 專注於元組的第一個元素,但不會忘記第二個欄位中的內容。

一旦我們有了焦點,我們就可以談談我們允許用鏡頭執行哪些操作。鑑於 Lens s a,當給定 s 型別的資料型別時,我們可以關注特定的 a,我們可以

  1. 通過忘記附加的上下文或提取 a
  2. 通過提供新值來替換 a

這些對應於眾所周知的 getset 操作,這些操作通常用於表徵鏡頭。

其他光學

我們可以用類似的方式談論其他光學器件。

光纖 專注於…
鏡片 產品的一部分
稜鏡 一部分金額
穿越 資料結構的零個或多個部分
同構

每個光學元件以不同的方式聚焦,因此,根據我們具有的光學器件型別,我們可以執行不同的操作。

組成

更重要的是,我們可以組合我們迄今為止所討論的兩種光學器件中的任何一種,以指定複雜的資料訪問。我們討論過的四種光學元件形成一個晶格,將兩個光學元件組合在一起的結果就是它們的上界。

StackOverflow 文件

例如,如果我們將鏡頭和稜鏡組合在一起,我們就會進行遍歷。其原因在於,通過它們(垂直)的構圖,我們首先關注產品的一部分,然後關注一部分的總和。結果是一個光學器件,它專注於我們資料的精確零點或一部分,這是一個特殊的遍歷情況。 (這有時也稱為仿射遍歷)。

在哈斯克爾

在 Haskell 中流行的原因是光學的表現非常簡潔。所有光學器件都只是某種形式的函式,可以使用函式組合來組合在一起。這樣可以實現非常輕量的嵌入,從而可以輕鬆地將光學器件整合到你的程式中。此外,由於編碼的細節,功能組合還自動計算我們組成的兩個光學系統的上限。這意味著我們可以在不進行顯式轉換的情況下將相同的組合器重複用於不同的光