Lens

Lens是一个接近语言级别的库,使用它可以方便的读取,设置,修改一个大的数据结构中某一部分的值。

view, over, set

Prelude> :m +Control.Lens
Prelude Control.Lens> view _1 ("abc", "def")
"abc"
Prelude Control.Lens> over _1 (++ "!!!") ("abc", "def")
("abc!!!","def")
Prelude Control.Lens> set _1 "!!!" ("abc", "def")
("!!!","def")
Prelude Control.Lens> view _2 ("abc", "def")
"def"

这里 _1, _2 则相当于元组的属性名,在 Lens 库中被称为 lens。

view 是一个 Getting,相当于Java语言中用来读取属性的 .getXXX()。

over 以及 set 是一个 Setting,相当于Java语言中用来设置属性的 .setXXX()。

view l s 读取数据结构 s 中字段 l' 的值。

set l s 设置数据结构 s 中字段 l' 的值。

而 over l f s 则通过调用函数 f 修改数据结构 s 中字段 l' 的值。

view, over, set的操作符版本

Prelude> :m +Control.Lens
Prelude Control.Lens> ("abc", "def") ^. _1
"abc"
Prelude Control.Lens> ("abc", "def") & _1 %~ (++ "!!!")
("abc!!!","def")
Prelude Control.Lens> ("abc", "def") & _1 .~ "!!!"
("!!!","def")
Prelude Control.Lens> ("abc", "def") ^. _2
"def"
Prelude Control.Lens> _2 %~ (++ "***") $ ("abc", "def")
("abc","def***")
Prelude Control.Lens> _2 .~ "***" $ ("abc", "def")
("abc","***")

view l s ≡ s ^. l

set l v s ≡ l .~ v $ s ≡ s & l .~ v

over l f s ≡ l %~ f $ s ≡ s & l %~ f

view, over, set 的 State 版本

Prelude Control.Lens Control.Monad.State> evalState (use _1) ("abc","def")
"abc"
Prelude Control.Lens Control.Monad.State> execState (do _1 .= "!!!"; _2 .= "***") ("abc", "def")
("!!!","***")
Prelude Control.Lens Control.Monad.State> execState (do _1 %= (++ "!!!"); _2 %= (++ "***")) ("abc", "def")
("abc!!!","def***")

preview, review

Prelude Control.Lens> view _Left (Left "abc")
"abc"
Prelude Control.Lens> view _Right (Right "abc")
"abc"
Prelude Control.Lens> view _Just (Just "abc")
"abc"
Prelude Control.Lens> preview _Left (Left "abc")
Just "abc"
Prelude Control.Lens> review _Left "abc"
Left "abc"
  • preview 和 review 函数处理 Either 这样的和类型

    preview 函数向上走一个分支。

    review 函数向下走一个分支。

preview, review 的操作符版本

Prelude Control.Lens> Left "abc" ^?! _Left
"abc"
Prelude Control.Lens> Left "abc" ^? _Left
Just "abc"
Prelude Control.Lens> Right "abc" ^? _Left
Nothing
Prelude Control.Lens> Right "abc" ^? _Right
Just "abc"
Prelude Control.Lens> _Left # "abc"
Left "abc"

preview l x ≡ x ^? l

review l x ≡ l # x

toListOf 及其操作符版本

Prelude Control.Lens> toListOf traverse [1,2,3]
[1,2,3]
Prelude Control.Lens> toListOf (traverse.traverse) [[1,2],[3]]
[1,2,3]
Prelude Control.Lens> toListOf both (1,2)
[1,2]
Prelude Control.Lens> toListOf _1 (4, 1)
[4]
Prelude Control.Lens> [[1,2],[3]] ^..traverse.traverse
[1,2,3]
Prelude Control.Lens> (1,2) ^..both
[1,2]
Prelude Control.Lens> (4, 1) ^.._2
[1]

to

Prelude Control.Lens> view (_1 . to negate) (3,5)
-3
Prelude Control.Lens> (3,5)^._1.to negate
-3
Prelude Control.Lens> views _1 negate (3,5)
-3
Prelude Control.Lens Control.Monad.State> evalState (use (_1 . to negate)) (3,5)
-3
Prelude Control.Lens Control.Monad.State> evalState (uses _1 negate) (3,5)
-3
Prelude Control.Lens> preview (_Just .to (+2)) (Just 3)
Just 5
Prelude Control.Lens> previews _Just (+2) (Just 3)
Just 5

to 操作符可以把普通函数提升为 Getter。

view + to = views

use + to = uses

preview + to = previews

mapped

Prelude Control.Lens> over mapped (+1) [1,2,3]
[2,3,4]
Prelude Control.Lens> set mapped 5 [1,2,3]
[5,5,5]
Prelude Control.Lens> over (mapped._1) (+1) [(1,2),(3,4)]
[(2,2),(4,4)]
Prelude Control.Lens> set (mapped.mapped) 5 [[1],[2]]
[[5],[5]]
Prelude Control.Lens> [[1],[2]] & mapped.mapped .~ 5
[[5],[5]]
Prelude Control.Lens> mapped %~ (+1) $ [1,2,3]
[2,3,4]

mapped 操作符可以把普通函数提升为 Functor。

ix

Prelude Control.Lens> [1,2,3] ^? ix 1
Just 2
Prelude Control.Lens> [1,2,3] ^?! ix 1
2
Prelude Control.Lens> [1,2,3] & (ix 1) .~ 20
[1,20,3]

at

relude Control.Lens> import qualified Data.Map as Map
Prelude Control.Lens Map> Map.fromList [(1,"world")] ^.at 1
Just "world"
Prelude Control.Lens Map> Map.fromList [(1,"world")] ^.ix 1
"world"
Prelude Control.Lens Map> at 1 ?~ "hello" $ Map.empty
fromList [(1,"hello")]
Prelude Control.Lens Map> ix 1 ?~ "hello" $ Map.empty
fromList []

traverse

Prelude Control.Lens> [[1], [2], [3]] ^. traverse
[1,2,3]
Prelude Control.Lens> [1,2,3] ^.. traverse
[1,2,3]
Prelude Control.Lens> [[1], [2], [3]] ^.. traverse . traverse
[1,2,3]

non

Prelude Control.Lens> Just 3 ^. non 1
3
Prelude Control.Lens> Nothing ^. non 1
1

参考链接

Haskell/Lenses and functional references

Control.Lens.Tutorial

A Little Lens Starter Tutorial

Haskell语言学习笔记(38)Lens(1)的更多相关文章

  1. Haskell语言学习笔记(88)语言扩展(1)

    ExistentialQuantification {-# LANGUAGE ExistentialQuantification #-} 存在类型专用的语言扩展 Haskell语言学习笔记(73)Ex ...

  2. Haskell语言学习笔记(44)Lens(2)

    自定义 Lens 和 Isos -- Some of the examples in this chapter require a few GHC extensions: -- TemplateHas ...

  3. Haskell语言学习笔记(79)lambda演算

    lambda演算 根据维基百科,lambda演算(英语:lambda calculus,λ-calculus)是一套从数学逻辑中发展,以变量绑定和替换的规则,来研究函数如何抽象化定义.函数如何被应用以 ...

  4. Haskell语言学习笔记(69)Yesod

    Yesod Yesod 是一个使用 Haskell 语言的 Web 框架. 安装 Yesod 首先更新 Haskell Platform 到最新版 (Yesod 依赖的库非常多,版本不一致的话很容易安 ...

  5. Haskell语言学习笔记(20)IORef, STRef

    IORef 一个在IO monad中使用变量的类型. 函数 参数 功能 newIORef 值 新建带初值的引用 readIORef 引用 读取引用的值 writeIORef 引用和值 设置引用的值 m ...

  6. Haskell语言学习笔记(39)Category

    Category class Category cat where id :: cat a a (.) :: cat b c -> cat a b -> cat a c instance ...

  7. Haskell语言学习笔记(64)Lens(4)

    安装 lens-tutorial Control.Lens.Tutorial $ cabal install lens-tutorial Installed lens-tutorial-1.0.3 P ...

  8. Haskell语言学习笔记(56)Lens(3)

    手动计算(view, over, set, to, _1) view l = getConst . l Const over l f = runIdentity . l (Identity . f) ...

  9. Haskell语言学习笔记(72)Free Monad

    安装 free 包 $ cabal install free Installed free-5.0.2 Free Monad data Free f a = Pure a | Free (f (Fre ...

随机推荐

  1. 使用js提交form表单的两种方法

    提交form表单的时候瑶族一些简单的验证,验证完后才能提交,避免无效提交. 1.当输入用户名和密码为空的时候,需要判断.这时候就用到了校验用户名和密码,这个需要在前端页面写:有两种方法,一种是用sub ...

  2. UOJ 393 【NOI2018】归程——可持久化并查集

    题目:http://uoj.ac/problem/393 题解:https://www.cnblogs.com/HocRiser/p/9368067.html 但过不了 UOJ 的 hack 数据.不 ...

  3. Tomcat 自动化部署

    Tomcat 自动化部署脚本 使用方法: ./autodeploy.sh test 其中autodeploy.sh 为脚本的文件名, test为war的文件名. #!/bin/sh now=`date ...

  4. Windows10安装.net3.5

    1.装载windows10映像 2.运行如下命令(注意修改盘符): Dism /online /enable-feature /featurename:NetFX3 /All /Source:F:\s ...

  5. ask 调用时间标签

    织梦时间调用标签大全(2012-08-03 12:50:13) 转载▼   分类: 织梦 织梦首页时间标签1,11-20 样式([field:pubdate  function='strftime(& ...

  6. sql 查询年龄

    SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- ...

  7. 杂项:SQLite

    ylbtech-杂项:SQLite SQLite,是一款轻型的数据库,是遵守ACID的关系型数据库管理系统,它包含在一个相对小的C库中.它是D.RichardHipp建立的公有领域项目.它的设计目标是 ...

  8. tomcat 加载顺序 web.xml文件详解

    一. 1.启动一个WEB项目的时候,WEB容器会去读取它的配置文件web.xml,读取<listener>和<context-param>两个结点. 2.紧急着,容创建一个Se ...

  9. 利用百度翻译API,获取翻译结果

    利用百度翻译API,获取翻译结果 translate.py #!/usr/bin/python #-*- coding:utf-8 -*- import sys reload(sys) sys.set ...

  10. 关于json_encode()的使用注意

    json_encode($json_str,true)在一般情况下可以返回一个数组,但当$json_str的字符编码是GBK或其它时,返回的是一个 空数组,必须用iconv(‘gbk’,‘ut8//I ...