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的更多相关文章

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

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

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

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

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

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

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

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

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

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

  6. Haskell语言学习笔记(28)Data.Map

    Map Prelude> import Data.Map as Map Prelude Map> :set -XOverloadedLists Prelude Map> Overlo ...

  7. Haskell语言学习笔记(93)Data.Text

    Data.Text.Read Prelude> :set -XOverloadedStrings Prelude> :m +Data.Text.Read Prelude Data.Text ...

  8. Haskell语言学习笔记(81)Data.Typeable

    Data.Typeable 利用 Data.Typeable,可以打印动态类型信息. class Typeable (a :: k) where typeRep# :: TypeRep a typeR ...

  9. Haskell语言学习笔记(77)Data.HashSet

    安装 unordered-containers $ cabal install unordered-containers Installed unordered-containers-0.2.9.0 ...

随机推荐

  1. Servlet 串联过滤器

    1. 串联Servlet过滤器的工作流程 2. 创建两个过滤器 MyFilter1和MyFilter2 1) MyFilter1 package com.example.filter; import ...

  2. 在ubuntu中安装luci解决iwinfo.h No such file or directory问题

    问题: src/luci-bwc.c:35:20: fatal error: iwinfo.h: No such file or directorycompilation terminated.mak ...

  3. 【Spring学习笔记-3.1】让bean获取spring容器上下文(applicationContext.xml)

    *.hl_mark_KMSmartTagPinkImg{background-color:#ffaaff;}*.hl_mark_KMSmartTagBlueImg{background-color:# ...

  4. zabbix 安装错误汇总

    由于公司业务需要,当前zabbixserver的压力较大,需要安装一个proxy缓解压力,开始慢慢琢磨proxy的安装.这些文档网上很多,就不在多说了.只把自己遇见的错误拿出来共享下 Zabbixpr ...

  5. HTTP Status 500 - The absolute uri: http://java.sun.com/jsp/jstl/core cannot-报错解决方法

    操作:jsp文件里面添加<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"   % ...

  6. shell 13文件包含

    同其他语言一样,shell也可以包含外部脚本.执行引用脚本可以使用source或 . 示例1 test.sh #shell #!/bin/sh echo "test.sh开始执行" ...

  7. servlet的讲解

    https://www.ibm.com/developerworks/cn/java/j-lo-servlet/

  8. volotile关键字的内存可见性及重排序

    在理解volotile关键字的作用之前,先粗略解释下内存可见性与指令重排序. 1. 内存可见性 Java内存模型规定,对于多个线程共享的变量,存储在主内存当中,每个线程都有自己独立的工作内存,并且线程 ...

  9. 如何在一个js文件中引入另外的js文件

    例如想要在a.js中引用b.js.c.js和d.js document.write("<script language='javascript' src='b.js'></ ...

  10. 下载任意版本的Chromium

    Download Chromium You can test Chrome builds or Chromium builds.  Chrome builds have the most infras ...