gpt4 book ai didi

scala - 镜头和部分镜头有什么区别?

转载 作者:行者123 更新时间:2023-12-04 00:09:40 26 4
gpt4 key购买 nike

“镜头”和“部分镜头”在名称和概念上似乎非常相似。它们有何不同?在什么情况下我需要使用其中一种?

标记 Scala 和 Haskell,但我欢迎与任何具有镜头库的函数式语言相关的解释。

最佳答案

根据 Haskell lens 的说法,描述部分镜头——我以后将称之为部分镜头。命名法、棱镜(除了它们不是!参见 Ørjan 的评论)——我想先从不同的角度看待镜片本身。

一个镜头Lens s a表示给定 s我们可以“关注” s 的子组件在类型 a ,查看它,更换它,并且(如果我们使用镜头系列变体 Lens s t a b )甚至改变它的类型。

一种看待这种情况的方法是 Lens s a见证 s 之间的同构,等价和元组类型 (r, a)对于某些未知类型r .

Lens s a ====== exists r . s ~ (r, a)

这给了我们我们需要的东西,因为我们可以拉动 a出来,替换它,然后通过等价向后运行,得到一个新的 s没有更新 a .

现在让我们花一点时间通过代数数据类型来刷新我们的高中代数。 ADT 中的两个关键运算是乘法和求和。我们写类型 a * b当我们有一个类型由具有 a 的项目组成时和 b我们写 a + b当我们有一个由 a 的项目组成的类型时或 b .

在 Haskell 中,我们写 a * b(a, b) ,元组类型。我们写 a + bEither a b , 任一种类型。

产品代表捆绑在一起的数据,总和代表捆绑在一起的选项。产品可以代表有很多东西只有一个你想(一次)选择的想法,而总和代表失败的想法,因为你希望选择一个选项(比如在左侧)但相反解决另一个(沿着右边)。

最后,总和和产品是分类对偶。就像大多数 PL 所做的那样,它们合二为一,让你处于一个尴尬的境地。

因此,让我们看看当我们将上面的镜头公式(部分)二元化时会发生什么。
exists r . s ~ (r + a)

这是 s 的声明是类型 a或其他一些东西 r .我们有一个 lens - 类似的东西在其核心深处体现了选择(和失败)的概念。

这正是棱镜(或部分透镜)
Prism s a ====== exists r . s ~ (r + a)
exists r . s ~ Either r a

那么这对于一些简单的例子是如何工作的呢?

好吧,考虑一下“取消”列表的棱镜:
uncons :: Prism [a] (a, [a])

相当于这个
head :: exists r . [a] ~ (r + (a, [a]))

并且比较明显的是 r这里需要:完全失败,因为我们有一个空列表!

证实类型 a ~ b我们需要编写一种方法来转换 a变成 bb进入 a使它们相互颠倒。让我们这样写是为了通过神话函数来描述我们的棱镜
prism :: (s ~ exists r . Either r a) -> Prism s a

uncons = prism (iso fwd bck) where
fwd [] = Left () -- failure!
fwd (a:as) = Right (a, as)
bck (Left ()) = []
bck (Right (a, as)) = a:as

这演示了如何使用这种等价性(至少在原则上)来创建棱镜,并且还表明当我们使用类似 sum 的类型(如列表)时,它们应该感觉非常自然。

关于scala - 镜头和部分镜头有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32223859/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com