makePrimss 的用例和示例

2024-03-08

我不清楚 makeLense 和 makePrisms 之间的区别?

我知道当我们想要访问嵌套结构/数据时,请像这样使用 makeLense :

data Point = Point { _x :: Int, _y :: Int}
data Test= Test {_name :: String, _position :: Point} 

makeLenses ''Point
makeLenses ''Test

然后我们就可以访问或者修改Test或者Point的组件了。例如我们定义一个函数:

modify :: Test -> Test
modify = over (position . x) (*8)

所以我们可以有:

let t1 = Test {_name= "Me", _position = Point {_x = 3, _y = 8}}

then

modify t1

将会:

Test {_name = "Me", _position = Point {_x = 24, _y = 8}}

但是,我不知道在上面的例子中何时以及如何使用 makePrisms !


为了理解这一点,您必须了解类型、类型变量、代数数据类型(和和乘积类型),并且还必须了解类型类和Functor特别是类型类。如果您不理解这些内容,请为此页面添加书签,然后继续理解它们,可能会使用我为此目的而帮助开发的资源,以说明和解释这些基础知识:http://happylearnhaskelltutorial.com http://happylearnhaskelltutorial.com

因此,在讨论棱镜之前,您首先需要知道什么是镜头。

A Lens通常被描述为函数式 getter/setter,但这更多的是关于实现等等。

我现在想和你一起尝试一下描述的实验。

假设我有一页非常小的文字,上面有一些文字。现在,我递给你一块与该页面大小相同的纸板,只是它有一个用于放大镜的孔,用于聚焦于特定单词。该词位于该页面的特定位置。

所以我们有这两件事:一个页面和一个没有放大镜的放大镜“卡片”......如果我们放入一个玻璃,它会聚焦在页面上的特定位置。现在有人带来了另一页,上面有不同的文字,但布局与第一页相同。

很容易想象,您可以拿起那张卡片,将其放在新页面上,它会集中在同一位置的不同单词上。

除了放大镜之外,您还有一个特殊的“橡皮擦/打印机”玻璃,当您将其放入卡片中时,您可以擦除并在该页面上键入文字。

现在将其应用到镜头上,您可以通过这个示例看到,如果我们获取一条数据(一页文本),一个适合该数据的镜头(一张带有孔的卡片,与页面的形状相匹配) )和一个可以“获取”或“设置”(或者可能是其他东西)的函数(即放大镜或橡皮擦/打印机玻璃,或其他类型的眼镜),好吧,由此我们可以view从较大的数据(页面)中提取较小的数据(单词)来提取它......或者也许我们可以set将不同的匹配数据插入该页面上的位置...

lens :: :: Functor f => (s -> a) -> (s -> b -> t) -> (a -> f b) -> s -> f t

这个函数有什么作用?它creates具有某些功能的镜头。现在我们有了上面的框架了解了什么是镜头,我们就可以了解这个功能了。我对你说s变量代表“状态”,它对应于镜头聚焦的纸张类型。接下来我可以说的是atype 变量对应于镜头将聚焦的页面上的单词。关于什么b and t?他们是改造后的a and s如果我们决定改变值a,并且这种变化改变了它的类型。

是什么Functor那么呢?我们一会儿就会知道。好吧,首先让我们制作一个镜头来实现这一点。那么,回到我们的lens函数,它的第一个参数是“getter”函数,第二个参数是“setter”函数(因此是类型)。然后还有另一种说法。嗯,因为 Haskell 函数是柯里化的,所以实际上是返回类型:一个函数s -> f t。现在让我们制作那个镜头。

假设我们有一个值列表[(1,(5,9)), (2,(3,6))]我们想要制作一个聚焦于第二个嵌套元组中的第二个值的镜头。但这很愚蠢,因为你可以使用snd . snd正确的?是的,你可以,所以这不是一个很好的例子,但是所有更好的例子都更复杂,所以请耐心等待 - 我们会讲到它们,此外,你能snd.snd函数也设置,或者有一个函数应用于它?不,我不这么认为! :)(好吧好吧我知道你可以用fmap (const val)设置,但它也可以改变类型吗?好吧,如果你像 Edward Kmett 那样继续得出逻辑结论,那么实际上你最终会得到 Lens 的这种思路 - 这就是 Functor 的用武之地!)

sndOfSndLens = lens (snd.snd) (\(x,(y,z)) newZ -> (x,(y,newZ)))

那么我们得到了什么?我们得到了这种类型的函数sndOfSndLens :: Functor f => (a -> f t2) -> (t, (t1, a)) -> f (t, (t1, t2)).

因此,让我们明确我们的价值观:map (view sndOfSnd) [(1,(5,9)), (2,(3,6))] -> [9,6]好的!这有效...让我们在以下位置设置新值:map (set sndOfSnd 2000) [(1,(5,9)), (2,(3,6))] -> [(1,(5,2000)),(2,(3,2000))]好的...

如果只是 getter 或 setter,那很无聊,但还有一个函数叫做over它将采用一个镜头和一个变换函数,并在镜头焦点函数上运行该变换......所以让我们从每个函数中减去 10:map (over sndOfSnd (flip (-) 10)) [(1,(5,9)), (2,(3,6))] -> [(1,(5,-1)),(2,(3,-4))]这很酷!好吧,我会让您阅读镜头文档的其余部分,以了解所有其他功能,因为它们很深并且镜头组成,您也可以用它们做各种其他事情。

Prism

我答应我们会到达棱镜,看看我们在这里......镜头是一个特定的“光学器件”(同时,有时也令人困惑地指代整套光学器件,所以要小心) ,棱镜是另一种光学器件,幸运的是完全具体。如果镜头是一种用于聚焦于物体特定部分的光学器件product 代数数据类型,然后 Prims 做同样的事情sum类型。这就是为什么我们能够制作一款谈论配对的镜头((,))因为他们是product类型...也就是说,它们将两种类型合二为一。镜头可让您专注于一件作品或穿过这些作品的路径。顺便说一句,我们上面创建的镜头可以通过组合更通用的内置镜头来轻松定义:_2 . _2。还有我们讨论的所有镜头功能的操作员版本。他们看起来很疯狂,但他们有逻辑。了解有关他们的信息!

棱镜让您专注于一个path通过一个sum type。有什么好的例子吗?好吧,假设我们已经考虑过Either数据类型。它是Either a b它被定义为data Either a b = Left a | Right b。于是就有了对应的prism函数让我们构建一个与上面的值相同的 Prism。如果我们使用内置的会发生什么_Left它集中在左侧Either,但我们只有一个Right 10价值?让我们看看...但首先,我们应该让您知道我们不能使用view不再需要,因为它可能不起作用,所以我们需要使用preview这将返回一个可能的值fail(抱歉,剧透!):

preview _Left (Left 10) -> Just 10然后是Right one? preview _Left (Right 10) -> Nothing。好吧,这很甜蜜。

The set函数工作正常,因为如果它没有意义,它可能会默默地失败:set _Left 30 (Left 10) -> Left 30。当它不起作用时会发生什么?set _Right 30 (Left 10) -> Left 10没错,什么都没有。

酷...希望这能解释镜头和棱镜。它们是两个非常有用的光学器件。镜头库是full所以我鼓励你看看它们

那原来的问题呢?

原来的问题是关于makeLenses and makePrisms。这些是模板 haskell 表达式(也就是说,它们是元编程/类似于宏,但类型宏),它们允许您根据自己的数据类型自动构建自己的镜头和/或棱镜。希望现在当您选择其中之一以及它们有何不同时,它会更有意义。这至少会让您大致了解它们的不同之处。要真正理解,您应该阅读文档并查找所有其他可能的功能和光学器件。

欢迎来到超酷的镜头世界!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

makePrimss 的用例和示例 的相关文章

  • 将数据类型设置为 Kind * -> * 这不是函子

    布伦特 约尔吉类型分类百科全书 https www haskell org haskellwiki Typeclassopedia给出以下练习 举一个类型的例子 gt 不能将其制成 的实例Functor 不使用undefined 请告诉我什
  • Haskell 下划线与显式变量

    我已经学习 Haskell 几个星期了 我有一个关于下划线的使用的问题 作为函数参数 我认为用一个具体的例子来问我的问题会更好 假设我想定义一个函数 根据提供的索引提取列表的元素 是的 我意识到 已经是预先定义的 我可以定义该函数的两种方法
  • Haskell:无法预期类型“Integer”与实际类型“Int”

    我已经盯着这段代码有一段时间了 但我无法理解该错误消息 divisors Integer gt Integer divisors n t t lt 1 n mod n t 0 length a gt Integer length 0 len
  • 如何在 Haskell 中向右或向左移动列表的 1 个元素?

    嗨 我一直在寻找答案 但找不到 假设我们有一个像这样的列表 1 10 4 5 3 我怎样才能将 5 向左移动 使这个列表变成 1 10 5 4 3 我尝试过了swapElementsAt通过找到该元素的索引 但它看起来非常不足 swapEl
  • 将两个 Int 值相除以获得 Float 的正确方法是什么?

    我想分两份IntHaskell 中的值并获得结果Float 我尝试这样做 foo Int gt Int gt Float foo a b fromRational a b 但 GHC 版本 6 12 1 告诉我 无法将预期类型 Intege
  • 规范化且不可变的数据模型

    Haskell如何解决 规范化不可变数据结构 问题 例如 让我们考虑一个表示前女友 男友的数据结构 data Man Man name String exes Woman data Woman Woman name String exes
  • Haskell Stack 从 github 安装包依赖项

    是否可以使用 Haskell 堆栈从 github 安装软件包的版本 例如在一个 cabal or a stack yaml文件 如何在 git repo branch revision 上指向依赖项 对于堆栈 The 的文档stack y
  • Haskell:Data.Numbers.Primes 库在哪里?

    我尝试导入 Data Numbers Primes import Data Numbers Primes 伦哈斯克尔给了我 5 hs 1 8 Could not find module Data Numbers Primes Use v t
  • 有没有更好的方法将 UTC 时间转换为大纪元时间?

    我想将文件的修改时间设置为从 exif 数据获取的时间 为了从 exif 获取时间 我发现 Graphics Exif getTag Exif gt String gt IO Maybe String 要设置文件修改时间 我发现 Syste
  • 如何在haskell中获取变量名称

    我来到 haskell 时有一些 c 背景知识 想知道是否有类似的 define print a printf s d n a a int a 5 print a 应该打印 a 5 这是 augustss 提到的 TH 解决方案 LANGU
  • Haskell:IORef 的性能

    我一直在尝试在 Haskell 中编码一个需要使用大量可变引用的算法 但与纯粹的惰性代码相比 它 也许并不奇怪 非常慢 考虑一个非常简单的例子 module Main where import Data IORef import Contr
  • : 中缀运算符在 Haskell 中的作用是什么?

    我正在阅读Haskell 简要介绍 http www haskell org tutorial index html 这不是那么温和 并且它反复使用 操作符而不直接解释它的作用 那么 它到底有什么作用呢 是 前置 运算符 x xs 返回一个
  • 这个对自身单位的列表理解是如何工作的?

    在 haskell IRC 频道中有人问 是否有一种简洁的方法来定义一个列表 其中第 n 个条目是之前所有条目的平方和 我认为这听起来像一个有趣的谜题 递归定义无限列表是我真正需要练习的事情之一 所以我启动了 GHCi 并开始尝试递归定义
  • Haskell 标准库是什么?

    GHC专用库可以称为标准库吗 或者只有 Haskell 2010 报告中的那些才算数 许多 GHC 库可以通过 Haskell 报告中的函数来实现 可能与 C 绑定相结合 但其他语言依赖于 GHC 特定的扩展 因为语言报告中定义的当前 Ha
  • Data.Sequence 中的 inits 和 tails 如何工作?

    Louis Wasserman 编写了当前的实现inits and tails in Data Sequence 他表示它们非常高效 事实上 只要查看代码 我就可以看到 无论它们在做什么 它们都是以干净 自上而下的方式进行的 这往往会给惰性
  • ST monad 是如何工作的?

    我知道 ST monad 有点像 IO 的弟弟 而 IO 又是添加了状态 monadRealWorld魔法 我可以想象状态 也可以想象 RealWorld 以某种方式放入 IO 中 但每次我写一个类型签名ST the sST monad 的
  • 如何在Haskell中实现词法分析器和解析器

    我在这里得到了这段代码 它是用Haskell结构的命令式编程语言编写的程序 所以问题是 我如何为这种语言实现词法分析器和解析器 该程序被定义为一系列语句有 6 种类型 goto write stop if goto 和 int int n
  • C++ 概念与 Haskell 类型类有何不同?

    Concepts TS 中的 C 概念最近已合并到 GCC 主干中 概念允许人们通过要求类型满足概念的条件 例如 可比较 来约束通用代码 Haskell 有类型类 我对 Haskell 不太熟悉 概念和类型类如何相关 概念 由概念 TS 定
  • 关于“没有绑定的类型签名”的错误

    我在 Haskell 中遇到 ASCII 问题 fromEnum Char gt Int toEnum Int gt Char offset Int offset fromEnum A fromEnum a toUpper Char gt
  • Haskell:需要了解 Functor 的签名

    有人能给我解释一下 Functor 的签名吗 Prelude gt info Functor class Functor f gt where fmap a gt b gt f a gt f b lt a gt f b gt f a 我不明

随机推荐

  • 使用路由时将 match param 和 props 传递到 React 组件中

    我有一个功能性反应组件 想要为我的组件中选定的人呈现一些属性 所以我首先绘制一个简单的列表 其中包含每个人的链接 props persons map person i gt return li person name li 然后我制定路线
  • String 和 Char 类型在 .NET 中如何存储在内存中?

    我需要存储一个语言代码字符串 例如 en 它始终包含 2 个字符 将类型定义为 String 还是 Char 更好 private string languageCode vs private char languageCode 或者还有其
  • 在网络应用程序中显示文件类型图标?

    在桌面应用程序中 您通常可以获取特定文件类型的底层操作系统图标并将其显示给用户 在网络应用程序中 我无法使用此类功能 因此看起来我可能需要提供自己的图标集 有谁知道有哪些针对常见图标类型的经过良好许可的免费图标集 我找到了一个github上
  • 处理 AJAX 请求上的 SAML 重定向

    我有几个 AngularJS 应用程序 全部使用 Spring Java 和 SAML 2 0 进行 SSO 利用 Spring Security SAML 扩展 我的 SSO ID 提供商是 OpenAM 一切运行良好 但是 我遇到了一种
  • 是否应该将依赖项注入比需要的更多“级别”?

    我正在使用 SOLID 原则编写 C ASP NET MVC Web 应用程序 我写了一个ViewModelService 这取决于AccountService and a RepositoryService 所以我将这两个服务注入到Vie
  • numpy 数组的缓存装饰器

    我正在尝试为具有 numpy 数组输入参数的函数制作一个缓存装饰器 from functools import lru cache import numpy as np from time import sleep a np array 1
  • 如何将自定义包添加到 Dymola/Modelica 的启动路径中?

    我有一个自定义包 我发现自己在 Dymola 模型中重复使用该包 并且我想将此包放在一个公共目录中 每当我启动 Dymola 时都会自动加载该目录 我当前的策略是在加载我正在处理的模型时加载自定义包 然后保存总计 这并不优雅 因为自定义包的
  • 如何将轴移动到图表中心?

    我需要在原点位于屏幕中心 或中心附近的某个位置 但不一定在中心 的坐标系上绘制一个函数 并且我需要绘制轴 以便它们在原点交叉 轴也应该有标签和抽动以及箭头 我不知道如何有效地做到这一点 到目前为止 在我的代码中 我手动设置了抽动的偏移量 并
  • phpMyAdmin 抛出 #2002 无法登录 mysql 服务器 phpmyadmin

    我已经在本地计算机上安装了MySQL服务器企业版5 1 现在我想安装phpMyAdmin 但它不起作用 我已将 phpMyAdmin 解压到我的服务器根目录并浏览到 localhost phpMyAdmin setup index php
  • 如何使用 wkhtmltopdf 在页眉/页脚 html 中进行页码编号?

    我正在开发一个电子发票系统 我们的功能之一是生成发票的 PDF 并邮寄它们 我们有多个发票模板 稍后还会创建更多模板 因此我们决定使用 HTML 模板 生成 HTML 文档 然后将其转换为 PDF 但我们面临着 wkhtmltopdf 的一
  • ios 标签栏自定义图像

    我在工作ios我需要定制的应用程序tabbar像是this http postimage org image jxm57t89j 首先我创建了5个viewcontrollers导航控制器中的每一个 然后把它们放进去tabbbarcontro
  • Symfony onFlush Doctrine 监听器

    嗨 我有一个 onFlush 监听器
  • 在新窗口中打开图像

    如何使用其在新窗口中打开图像id function swipe var largeImage document getElementById largeImage largeImage style display block largeIm
  • 更改Android自定义SurfaceView的大小

    我正在尝试为 Android 应用程序创建 2D 游戏引擎 我已经关注了本教程 http www droidnova com 2d tutorial series part ii 772 html 这对于创建全屏显示效果很好 但我不想要这样
  • servicestack ormlite 中的分页

    我正在寻找一种在 ormlite 中实现分页的好方法 我发现了另一种question https stackoverflow com questions 15705419 passing params expression results
  • 从 Intent.createChooser 获取选择的应用程序

    我正在尝试捕捉结果Intent createChooser了解用户选择共享哪个应用程序 我知道有很多与此相关的帖子 如何知道用户在使用意图选择器时选择了哪个应用程序 https stackoverflow com questions 106
  • Filemaker GetAs...如何在网页上显示容器字段?

    我有一个 ASP Net 应用程序 需要显示存储在 Filemaker 容器字段中的图像 我的查询语句如下所示 SELECT GetAs Image JPG FROM UA Item Pictures WHERE Stock Number
  • PyGame Space Invaders 游戏 - 让外星人一起移动

    我已经使用 PyGame 模块在 Python 中创建了一个 Space Invaders 克隆 但是当它们到达游戏屏幕边缘时 让它们一起向下移动时遇到了一些困难 当外星人到达游戏屏幕边缘时 我该如何做到这一点 他们都同时改变方向并下降一个
  • 多对一,全部删除孤儿,将属性设置为 null 但实体未删除

    使用 NHibernate v3 0 我有一个与此类似的课程 class Foo bool barActive Bar bar Bar 实例完全由 Foo 内部管理 当 barActive 为 true 时 bar 被设置为 Bar 实例
  • makePrimss 的用例和示例

    我不清楚 makeLense 和 makePrisms 之间的区别 我知道当我们想要访问嵌套结构 数据时 请像这样使用 makeLense data Point Point x Int y Int data Test Test name S