Haskell语言学习笔记(36)Data.List.Zipper
ListZipper 模块
$ cabal install ListZipper
Installed ListZipper-1.2.0.2
Prelude> :m +Data.List.Zipper
Prelude Data.List.Zipper>
Zipper 和 ListZipper
Zipper 是一种带焦点(focus,也称游标, cursor)的数据结构。使用 Zipper 可以很方便的在底层数据结构中进行遍历,更新,插入,删除等操作。
ListZipper 是建立在 List 这种数据结构上的 Zipper,可以理解为带焦点(游标)的List。
ListZipper 函数示例
Prelude Data.List.Zipper> z = fromList [3,4,5]
Prelude Data.List.Zipper> z
Zip [] [3,4,5]
Prelude Data.List.Zipper> replace 6 z
Zip [] [6,4,5]
Prelude Data.List.Zipper> toList z
[3,4,5]
Prelude Data.List.Zipper> emptyp z
False
Prelude Data.List.Zipper> beginp z
True
Prelude Data.List.Zipper> end z
Zip [5,4,3] []
Prelude Data.List.Zipper> cursor z
3
Prelude Data.List.Zipper Data.Function> z & right & right
Zip [4,3] [5]
Prelude Data.List.Zipper Data.Function> z & insert 6
Zip [] [6,3,4,5]
Prelude Data.List.Zipper Data.Function> z & push 6
Zip [6] [3,4,5]
Prelude Data.List.Zipper Data.Function> z & right & pop
Zip [] [4,5]
Prelude Data.List.Zipper Data.Function> z & right & foldrz (\z b -> cursor z + b) 0
9
Prelude Data.List.Zipper Data.Function> z & right & foldlz (\b z -> cursor z + b) 0
9
Prelude Data.List.Zipper> extractz z
3
Prelude Data.List.Zipper> duplicatez z
Zip [] [Zip [] [3,4,5],Zip [3] [4,5],Zip [4,3] [5]]
Prelude Data.List.Zipper> extendz (\z -> show (cursor z)) z
Zip [] ["3","4","5"]
import Control.Monad.State
import Data.List.Zipper
f :: State (Zipper Int) [Int]
f = do
modify right -- [3],[4,5]
modify $ replace 6 -- [3],[6,5]
modify $ insert 7 -- [3],[7,6,5]
gets toList -- [3,7,6,5]
main = print . evalState f $ fromList [3,4,5]
理解 ListZipper
data Zipper a = Zip ![a] ![a] deriving (Eq,Show)
fromList :: [a] -> Zipper a
fromList as = Zip [] as
toList :: Zipper a -> [a]
toList (Zip ls rs) = reverse ls ++ rs
left :: Zipper a -> Zipper a
left (Zip (a:ls) rs) = Zip ls (a:rs)
left z = z
right :: Zipper a -> Zipper a
right (Zip ls (a:rs)) = Zip (a:ls) rs
right z = z
insert :: a -> Zipper a -> Zipper a
insert a (Zip ls rs) = Zip ls (a:rs)
delete :: Zipper a -> Zipper a
delete (Zip ls (_:rs)) = Zip ls rs
delete z = z
push :: a -> Zipper a -> Zipper a
push a (Zip ls rs) = Zip (a:ls) rs
pop :: Zipper a -> Zipper a
pop (Zip (_:ls) rs) = Zip ls rs
pop z = z
replace :: a -> Zipper a -> Zipper a
replace a (Zip ls (_:rs)) = Zip ls (a:rs)
replace _ z = z
- data Zipper a = Zip ![a] ![a] deriving (Eq,Show)
ListZipper 是建立在List 上的数据结构,它包含两个List,其中第二个List的第一个元素是当前的焦点。
也就是说左边的 List 包含焦点之前的元素,而右边的 List 则包含焦点及其之后的元素。 - fromList as = Zip [] as
fromList 将 List 参数 as 转换成 Zipper,当前焦点在as的第一个元素。 - toList (Zip ls rs) = reverse ls ++ rs
toList 将 Zipper 转换成 List。 - left (Zip (a:ls) rs) = Zip ls (a:rs)
left 函数将当前焦点左移一个元素。即左边 List 的第一个元素被移至右边 List 的最前端。 - right (Zip ls (a:rs)) = Zip (a:ls) rs
right 函数将当前焦点右移一个元素。即右边 List 的第一个元素被移至左边 List 的最前端。 - insert a (Zip ls rs) = Zip ls (a:rs)
insert 函数在当前焦点处插入新元素。即在右边 List 的最前端插入新元素。 - delete (Zip ls (_:rs)) = Zip ls rs
delete 函数移除处位于焦点处的元素。即右边 List 的第一个元素被移除。 - push a (Zip ls rs) = Zip (a:ls) rs
push 函数在当前焦点之前插入新元素。即在左边 List 的最前端插入新元素。 - pop (Zip (_:ls) rs) = Zip ls rs
pop 函数移除位于焦点之前的一个元素。即左边 List 的第一个元素被移除。 - replace a (Zip ls (_:rs)) = Zip ls (a:rs)
replace 函数替换当前焦点处的元素。即右边 List 的第一个元素被替换。
Haskell语言学习笔记(36)Data.List.Zipper的更多相关文章
- Haskell语言学习笔记(88)语言扩展(1)
ExistentialQuantification {-# LANGUAGE ExistentialQuantification #-} 存在类型专用的语言扩展 Haskell语言学习笔记(73)Ex ...
- Haskell语言学习笔记(69)Yesod
Yesod Yesod 是一个使用 Haskell 语言的 Web 框架. 安装 Yesod 首先更新 Haskell Platform 到最新版 (Yesod 依赖的库非常多,版本不一致的话很容易安 ...
- Haskell语言学习笔记(20)IORef, STRef
IORef 一个在IO monad中使用变量的类型. 函数 参数 功能 newIORef 值 新建带初值的引用 readIORef 引用 读取引用的值 writeIORef 引用和值 设置引用的值 m ...
- Haskell语言学习笔记(79)lambda演算
lambda演算 根据维基百科,lambda演算(英语:lambda calculus,λ-calculus)是一套从数学逻辑中发展,以变量绑定和替换的规则,来研究函数如何抽象化定义.函数如何被应用以 ...
- Haskell语言学习笔记(39)Category
Category class Category cat where id :: cat a a (.) :: cat b c -> cat a b -> cat a c instance ...
- Haskell语言学习笔记(28)Data.Map
Map Prelude> import Data.Map as Map Prelude Map> :set -XOverloadedLists Prelude Map> Overlo ...
- Haskell语言学习笔记(93)Data.Text
Data.Text.Read Prelude> :set -XOverloadedStrings Prelude> :m +Data.Text.Read Prelude Data.Text ...
- Haskell语言学习笔记(81)Data.Typeable
Data.Typeable 利用 Data.Typeable,可以打印动态类型信息. class Typeable (a :: k) where typeRep# :: TypeRep a typeR ...
- Haskell语言学习笔记(77)Data.HashSet
安装 unordered-containers $ cabal install unordered-containers Installed unordered-containers-0.2.9.0 ...
随机推荐
- 转 JMeter之修改Sampler响应数据的编码格式
问题:JMeter的sampler响应数据中有中文时,会解析出错. JMeter的Sampler中的响应数据默认的编码格式是:ISO-8859-1.来自文件: jmeter.properties中的语 ...
- SSH pts 虚拟终端
昨天晚上小试了一下SSH,学到了一些乱七八糟的命令,知道了一种古老装逼的聊天方式:write.期间下定决心终于弄明白了pts/0之类的东西到底是什么东西. 先说pts/0吧,man里面是这样说的:pt ...
- 知识点查缺补漏贴01-进程间通讯之mmap文件共享
引文: 个人名言:“同一条河里淹死两次的人,是傻子,淹死三次及三次以上的人是超人”.经历过上次悲催的面试,决定沉下心来,好好的补充一下基础知识点.本文是这一系列第一篇:进程间通讯之mmap. 一.概念 ...
- bzoj 1767: [Ceoi2009]harbingers
Description 给定一颗树,树中每个结点有一个邮递员,每个邮递员要沿着唯一的路径走向capital(1号结点),每到一个城市他可以有两种选择: 1.继续走到下个城市 2.让这个城市的邮递员替他 ...
- bzoj4928: 第二题
Description 对于一棵有根树,定义一个点u的k-子树为u的子树中距离u不超过k的部分. 注意,假如u的子树中不存在距离u为k的点,则u的k-子树是不存在的. 定义两棵子树是相同的,当且仅当不 ...
- 更加灵活的编写控制层的方法____结合eval函数
结合EVAL函数,我们可以把API放到测试用例那边去,就可以使用一个定位元素,测试用例可以使用多个API 发现eval里面可以拼接str.那么写成这样更顺眼 eval("self.d ...
- 【转载】CSS + DIV 实现局部布局
HTML CSS + DIV实现局部布局 1.本章教大家掌握2种布局方式: 1)顶部导航菜单布局,效果图: 2)购物版块布局,效果图: 2.技术目标:使用div + ul-li实现导航菜单布局 ...
- ue4 多相机分屏与小地图效果实现教程
转自:http://blog.csdn.net/shenmifangke/article/details/51940007 通过使用ue4的UI和rendertarget来实现 优点就是可以随意设置 ...
- C++并发编成 03 线程同步
这一节主要讲讲线程同步的方式,C++ 11中提供了丰富的线程同步元语,如condition_variable,futrue,std::packaged_task<>,std::promis ...
- javaScript中对象属性的访问
有两种方式访问对象属性,一个是点操作符(.),一种是中括号操作符([ ]). 当你知道属性的名称时,使用点操作符: var myObj = { prop1: "val1", pro ...