kqr*_*kqr 18 haskell lenses haskell-lens
如果您浏览hackage上的Lens条目,Lens Github的回购,甚至谷歌关于Lens,您会发现许多部分参考资料,如介绍性教程/视频,示例,概述等.由于我已经了解了大部分基础知识,因此我正在寻找更完整的参考资料,以帮助我更多地了解高级功能.换句话说,我仍然不知道这意味着什么,并且找不到足够完整的资源来解释这个图形.想法?
kqr*_*kqr 34
黑线鳕是最好的深度资源.它们包含所有内容,但最初可能有点难以导航.只需浏览不同的模块,并记下哪些地方的心理记录,您将很快找到自己的方式.您链接的图表也是模块的非常好的映射.
但是,由于您说您不了解图形,我将假设您不需要高级或完整的参考.该图实际上是lens
包的各个部分的基本,高级概述.如果您不理解该图,您可能应该等待一些高级内容.
在阅读本文时,请记住,虽然lens
封装最初是作为一个包装的镜头开始,但现在包装中有许多种光学元件,它们遵循不同的规律并用于不同的事物."光学"是用于在数据结构上戳的类似镜头的东西的通用名称.
无论如何,这是我如何阅读图表.
现在,只需查看写入光学元件名称的方框顶部.
顶层,Fold
和Setter
,是,基本的光学lens
.可以想象,a Setter
是一个设置某个字段值的光学元件.我会在这里省略一些例子,因为你说你知道大部分基础知识,但实际上,当你这么做时
?> ellen & age .~ 35
Person { _name = "Ellen", _age = 35 }
Run Code Online (Sandbox Code Playgroud)
然后你就用age
了Setter
.
A Getter
是一种特殊的类型Fold
,允许您从数据结构中获取值.(A Fold
本身只允许你以某种方式结合的值到一个新的价值,而不是把他们救出来,因为它们.),一个Getter
是一种特殊的Fold
标记在从箭头指向的图形Getter
来Fold
.
如果你将a Fold
和a 组合在一起Setter
(也就是说你结合了循环一堆值的方法和一种设置单个值的方法),你得到一个Traversal
.A Traversal
是一个针对多个元素的光学元件,可让您设置或修改所有元素.
在图表的下方,如果你将a Getter
与a 结合起来就Traversal
得到了Lens
.这对你来说应该是熟悉的,因为镜头通常被称为"吸气剂和定位器的组合",你可以认为Traversal
它更强大Setter
.
我不会假装我知道了一大堆有关之间的关系Review
,Prism
,Iso
和Equality
.我理解它的方式,
Review
是一个函数的基本包装器b -> t
,b
它应该是t
结构内部的一个字段.因此,a Review
采用单个字段值,然后围绕它构造整个结构.这可能看起来很愚蠢,但它实际上与a相反Getter
,并且对构建棱镜很有用.Prism
允许您在分支类型中获取和设置值.这是对Either
什么Lens
是元组.你只能Either
用一个镜头来获取一个值,因为它会在它碰到Left
分支时爆炸.Iso
是一个非常强大的组合Lens
和Prism
,它允许你自由地通过光学看"左右逢源".虽然a Lens
允许您从高级别查看数据结构的精确部分,但Iso
您也可以从数据结构的精确部分查看到高级别.Equality
是......我不知道,对不起.类似的签名一开始Lens s t a b
可能会很吓人,所以我会尽快覆盖它的意思.如果你看一下Getter
,你会看到它的类型签名是
Getter s a
Run Code Online (Sandbox Code Playgroud)
如果我们考虑概念上的吸气剂,这似乎很熟悉.什么是吸气剂?它是从数据结构s
到a
该结构内部的单个值的函数.例如,函数Person -> Age
是从Person
对象获取年龄的getter .相应的Getter
只是签名
Getter Person Age
Run Code Online (Sandbox Code Playgroud)
这真的很简单.A Getter s a
是可以a
从内部获得的光学器件s
.
简化的Lens'
签名现在应该不那么可怕了.如果你不得不猜测,那是什么
Lens' Person Age
Run Code Online (Sandbox Code Playgroud)
?简单!这是一个Lens
可以获取和设置(记住镜头是getter和setter的组合?)Age
一个Person
值内的字段.因此,您应用于Getter s a
您的相同逻辑可以适用于Lens' s a
.
但那s t a b
部分呢?好吧,想想这种类型:
data Person a = { _idField :: a, address :: String }
Run Code Online (Sandbox Code Playgroud)
一个人可以通过某种识别价值识别并具有年龄.假设你被一个名字识别出来
carolyn :: Person String
carolyn = Person "Carolyn" "North Street 12"
Run Code Online (Sandbox Code Playgroud)
如果您有一个toIdNumber :: String -> Int
从字符串中生成ID号的函数怎么办?你可能想这样做:
?> carolyn & idField %~ toIdNumber
Person 57123 "North Street 12"
Run Code Online (Sandbox Code Playgroud)
但你不能idField :: Lens' (Person String) String
因为那个镜头只能处理String
s.它不知道将字符串转换为整数并将其粘贴到同一位置意味着什么.这就是我们拥有的原因Lens s t a b
.
我读取签名的方式是"如果你给我一个函数a -> b
,我会给你一个函数s -> t
",其中a
和b
两个都是指镜头的目标,s
并t
参考包含数据结构.具体例子:如果有的话
idField :: Lens (Person String) (Person Int) String Int
Run Code Online (Sandbox Code Playgroud)
我们可以做上面的转变.该镜头知道如何Person
使用字符串id字段并将其转换为具有Int
id字段的人.
因此,基本上,a Lens s t a b
可以被理解为"函数" (a -> b) -> (s -> t)
."给我一个(a -> b)
关于我的目标的转换,以及一个s
包含该目标的数据结构,我将返回一个t
已应用该转换的数据结构."
当然,它实际上并没有那么的功能-它比这更强大-但你可以给它把它变成该函数over
是的一部分Setter
.
盒子的内容只是每种光学元件的最常见和/或核心操作.他们的类型很多地说明了他们的所作所为,我将选择一些例子来说明我的意思.
通常,最重要的项目是你如何构建这种光学元件.例如,Getter
框中最顶部的项是to
函数,它Getter
从任何函数构造一个函数s -> a
.如果你使用这个功能,你可以Traversal
免费获得一个.Traversable
traverse
然后是下面的常见操作.例如,您可以view
在下面找到Getter
,这就是您使用a Getter
从数据结构中获取内容的方式.在Setter
,你发现over
和set
高涨.
(有趣的观察:大多数盒子似乎包含两个双重功能:一种创建光学器件的方法,以及一种使用它们的方法.有趣的是那些通常具有几乎相同的类型签名,但相互之间相互翻转.示例:
to :: (s -> a) -> Getter s a
view :: Getter s a -> (s -> a)
和
unto :: (b -> t) -> Review s t a b
review :: Review s t a b -> (b -> t)
我现在注意到了一些有趣的东西.)
我通常不会像写这篇文章一样仔细研究图形.大多数情况下,我只偷看Setter
,Getter
,Traversal
,Lens
和Prism
他们在哪里相对于彼此,因为那些是我最常用的光学器件.
当我知道我需要做某些事情时,我通常会快速浏览一下图形,看看哪些框包含类似于我想要做的操作.(例如,如果我有data Gendered a = Masculine a | Feminine a
,则_Right
类似于假设_Feminine
.)当我确定了这一点时,我会深入了解Haddocks中的那些模块(在本例中Prism
),搜索我需要的操作.
我学习光学以及如何使用它们的方式与学习一切相同.我发现一个真正的问题,光学是一个很好的解决方案,我试图解决它.我尝试了但是我失败了,我再试一次,我寻求帮助,我尝试尝试尝试.最终我会成功.然后我尝试稍微不同的东西.
通过实际使用它们的方式来使用它我收集了很多关于它们如何工作的有用经验.
在我开始写这篇文章之前,我认为你需要Prism
处理Maybe
值,因为Maybe
类型是分支,不是吗?不完全的!至少不超过List
你不需要Prism
处理的类型.
因为Maybe
类型是零个或一个元素的容器,所以实际上只需要Traversal
处理它.当你有两个分支可以包含不同的值,你开始需要的全部功能Prism
.(要构建一个Maybe
值,你仍然需要这个Review
.)
只有当我开始仔细阅读图表并探索模块以找出光学器件之间的实际,形式差异时,我才想到这一点.这是使用我的方法来学习东西的缺点.只要它有效,我就是它.有时会导致迂回的做事方式.