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 ...
随机推荐
- Python中的类(classes)
Python的类机制使用尽可能少的新语法和语义将类引入语言.python的类提供了面向对象程序设计语言所有的 标准特性:类继承机制允许有多个基类,一个派生类可以覆盖基类中的任何方法,一个方法可以使用相 ...
- 洛谷2530(codevs2098)化工厂装箱员
题目:https://www.luogu.org/problemnew/show/P2530 dp或搜索. dp做法就是 当前值+1 转移到 当前某一维为0.位置前进了c位 的地方.但没写. 写了搜索 ...
- MyBatis持久层框架使用总结 转载
MyBatis持久层框架使用总结 MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google co ...
- 阿里巴巴Java开发手册- 控制语句
1. [强制]在一个 switch 块内,每个 case 要么通过 break / return 等来终止,要么注释说明程序将继续执行到哪一个 case 为止 : 在一个 switch 块内,都必须包 ...
- netty搭建Tcp服务器实践
在netty基本组件介绍中,我们大致了解了netty的一些基本组件,今天我们来搭建一个基于netty的Tcp服务端程序,通过代码来了解和熟悉这些组件的功能和使用方法. 首先我们自己创建一个Server ...
- 一小时入门webpack
webpack现在已经成为了大众化的项目必要脚手架,基本上现在的很多项目都需要webpack,由于webpack的出现glup和grunt已经完败,今天我们来说一下webpack如何使用. 首先我们需 ...
- vs2015 去除 git 源代码 绑定,改成向tfs添加源码管理
除了下文的方法是将源码管理从git改成tfs之外,还要做以下几步即可 向tfs添加源码 打开源码管理(管理连接),双击打开你要向其中添加的tfs连接 选中该解决方案,右键 将解决方案添加到源码管理 嵌 ...
- python处理excel(二):写
代码参考自zhoujie.函数接口可参考该blog. 基本的write函数接口很简单: 新建一个excel文件 file = xlwt.Workbook() (注意这里的Workbook首字母是大写) ...
- sed简单用法
参数说明: -e 以指定的script来处理输入的文本文件 -f 以指定的script文件来处理输入的文本文件 -h 显示帮助 -n 仅显示script处理后的结果 -V 显示版本信息 -v 反选 动 ...
- 1030 Travel Plan (30 分)
1030 Travel Plan (30 分) A traveler's map gives the distances between cities along the highways, toge ...