gpt4 book ai didi

haskell - 镜片和 zipper 有什么区别?

转载 作者:行者123 更新时间:2023-12-03 10:38:52 24 4
gpt4 key购买 nike

这是在 Haskell 中使用 zipper 的示例:

data Tree a = Fork (Tree a) (Tree a) | Leaf a
data Cxt a = Top | L (Cxt a) (Tree a) | R (Tree a) (Cxt a)
type Loc a = (Tree a, Cxt a)

left :: Loc a -> Loc a
left (Fork l r, c) = (l, L c r)

right :: Loc a -> Loc a
right (Fork l r, c) = (r, R l c)

top :: Tree a -> Loc a
top t = (t, Top)

up :: Loc a -> Loc a
up (t, L c r) = (Fork t r, c)
up (t, R l c) = (Fork l t, c)

upmost :: Loc a -> Loc a
upmost l@(t, Top) = l
upmost l = upmost (up l)

modify :: Loc a -> (Tree a -> Tree a) -> Loc a
modify (t, c) f = (f t, c)

这是在 Clojure 中使用 zipper 的示例:
(use 'clojure.zip)
(require '[clojure.zip :as z])

user> (def z [[1 2 3] [4 [5 6] 7] [8 9]])
#'user/z

user> (def zp (zipper vector? seq (fn [_ c] c) z))
#'user/zp

user> zp
[[[1 2 3] [4 [5 6] 7] [8 9]] nil]

user> (-> zp down)
[[1 2 3] {:l [], :pnodes [[[1 2 3] [4 [5 6] 7] [8 9]]], :ppath nil, :r ([4 [5 6] 7] [8 9])}]

user> (first (-> zp down))
[1 2 3]

这是在 Haskell 中使用 Lens 的示例:
data Person = P { name :: String 
, addr :: Address
}
data Address = A { street :: String
, city :: String
, postcode :: String
}

setPostcode :: String -> Person -> Person
setPostcode pc p = p { addr = addr p { postcode = pc }}

这是在 Clojure 中使用镜头的示例。
(use 'lens)

(defrecord Address [street city postcode])
(defrecord Person [name age address])
(defrecord User [uid username identity password])

(def -postcode (mklens :postcode))
(def -city (mklens :city))
(def -street (mklens :street))
(def -address (mklens :address))
(def -age (mklens :age))
(def -name (mklens :name))
(def -uid (mklens :uid))
(def -username (mklens :username))
(def -identity (mklens :identity))
(def -password (mklens :password))

(-get -postcode home)

(-set -postcode home 500)

现在看来,lens 和 zippers 都是遍历嵌套数据结构的函数式方法。

我的问题是: 镜片和 zipper 有什么区别? 是否适合特定用例?

最佳答案

zipper 类似于游标:它们允许以有序的方式遍历树。他们通常的操作是up , down , left , rightedit . (名称可能因实现而异)

镜头是某种通用键(如“关联数据结构的键”)。该结构不需要订购。他们通常的操作是fetchputback并且与 get 非常相似和 assoc . (名称可能因实现而异)

因此,正如您所看到的, zipper 非常关注层次结构(上/下)和顺序(左/右),而镜头只是关注(因此得名)一条数据,这甚至可能是一个投影(那是什么在原始结构中并不存在)。

例如,在我正在进行的 Enliven 上的工作中,我有镜头可以让我专注于 HTML 文档中的单个类或样式属性。

关于haskell - 镜片和 zipper 有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22094971/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com