首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >全图的Control.Lens透镜

全图的Control.Lens透镜
EN

Stack Overflow用户
提问于 2013-10-15 12:43:12
回答 2查看 267关注 0票数 5

我有一张从A型到B型的总地图。

代码语言:javascript
复制
import qualified Data.Map as M
import Data.Maybe

tmGet k m = fromJust $ M.lookup k m

tmSet k v = M.insert k v

我使用Data.Map作为示例实现,但它可以是任何东西,例如Array甚至Bool-indexed元组:

代码语言:javascript
复制
tmGet True  = fst
tmGet False = snd

我希望有一个tmAt函数来构造一个透镜:

代码语言:javascript
复制
(42, 665) ^. tmAt True == 42
(42, 665) & tmAt False +~ 1 == (42, 666)

问题是如何用tmGettmSet (或tmModify)构建tmGet

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-10-15 13:16:08

如果你看Control.Lens模块的文档,有一个非常方便的图像,不同的部分的镜头包。因为您想要构造一个Lens,所以可以查看图的Lens部分。显示的最上面的函数是

代码语言:javascript
复制
lens :: (s -> a) -> (s -> b -> t) -> Lens s t a b

这将从一个吸气器和一个策划者构造一个透镜。

函数s -> a是一个getter --类型签名的意思是,“如果您给我一个数据结构s,我将从中选择一个a值。”s -> b -> t函数是setter,类型签名的意思是:“如果您给我一个s和一个新的值b,我将为您创建一个新的结构t。”(类型不同,因为镜片实际上可以改变事物的类型。)

如果您的getter是tmGet,而setter是tmSet,那么您可以用

代码语言:javascript
复制
tmAt :: Boolean -> Lens s t a b
tmAt b = lens (tmGet b) (tmSet b)

无论您的实际stab参数是什么。在元组的例子中,它应该是

代码语言:javascript
复制
tmAt :: Bool -> Lens (a, a) (a, a) a a

(换句话说,如果您给透镜一个函数a -> a,它可以将一个(a, a)-tuple转换成另一个(a, a)-tuple。)

如果您想要花哨,也可以将tmAt重写为

代码语言:javascript
复制
tmAt = lens <$> tmGet <*> tmSet
票数 3
EN

Stack Overflow用户

发布于 2013-10-15 13:12:28

一旦您将tmGettmSet定义为类型

代码语言:javascript
复制
tmGet :: k -> f v -> v
tmSet :: k -> f v -> v -> f v

您可以通过使用参数化的getter和setter来给透镜构造函数lens定义一系列透镜。下面是如何为Bool索引的一对

代码语言:javascript
复制
tmGet True  = fst
tmGet False = snd

tmSet True  (_,b) a = (a,b)
tmSet False (a,_) b = (a,b)

tmAt b = lens (tmGet b) (tmSet b)

现在在GHCI

代码语言:javascript
复制
>>> (42,665) ^. tmAt True
42
>>> (42,665) & tmAt False +~ 1
(42,666)
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19381552

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档