标签: zipper

更新嵌套结构的更清洁方法

说我有以下两个case classes:

case class Address(street: String, city: String, state: String, zipCode: Int)
case class Person(firstName: String, lastName: String, address: Address)
Run Code Online (Sandbox Code Playgroud)

和以下Person类的实例:

val raj = Person("Raj", "Shekhar", Address("M Gandhi Marg", 
                                           "Mumbai", 
                                           "Maharashtra", 
                                           411342))
Run Code Online (Sandbox Code Playgroud)

现在,如果我想更新zipCode,raj那么我将不得不做:

val updatedRaj = raj.copy(address = raj.address.copy(zipCode = raj.address.zipCode + 1))
Run Code Online (Sandbox Code Playgroud)

随着嵌套水平的提高,这将变得更加丑陋.是否有更清洁的方式(像Clojure的东西update-in)来更新这样的嵌套结构?

scala zipper case-class

122
推荐指数
7
解决办法
2万
查看次数

了解为什么Zipper是Comonad

这是对我上一个问题的答案的后续跟进.

假设我需要映射每个项目a:AList[A]b:B使用功能def f(a:A, leftNeighbors:List[A]): B和产生List[B].

显然,我不能只是map在列表上调用,但我可以使用列表拉链.拉链是一个在列表中移动的光标.它提供对当前element(focus)及其邻居的访问.

现在我可以替换我fdef f'(z:Zipper[A]):B = f(z.focus, z.left)并将这个新函数传递f'cobind方法Zipper[A].

这样的cobind工作:它f'用拉链调用,然后移动拉链,f'新的 "移动"拉链调用,再次移动拉链等等......直到拉链到达列表的末尾.

最后,cobind返回一个新的拉链类型Zipper[B],可以将其转换为列表,从而解决问题.

现在请注意之间的对称性cobind[A](f:Zipper[A] => B):Zipper[B]bind[A](f:A => List[B]):List[B]这就是为什么ListMonadZipperComonad.

是否有意义 ?

functional-programming scala zipper comonad

112
推荐指数
1
解决办法
2687
查看次数

Zipper Comonads,一般来说

给定任何容器类型,我们可以形成(以元素为中心的)Zipper并且知道这个结构是Comonad.最近在针对以下类型的另一个Stack Overflow问题中详细探讨了这个问题:

data Bin a = Branch (Bin a) a (Bin a) | Leaf a deriving Functor
Run Code Online (Sandbox Code Playgroud)

使用以下拉链

data Dir = L | R
data Step a = Step a Dir (Bin a)   deriving Functor
data Zip  a = Zip [Step a] (Bin a) deriving Functor
instance Comonad Zip where ...
Run Code Online (Sandbox Code Playgroud)

这是一个情况ZipComonad,虽然它的实例的建设是一个有点毛.也就是说,Zip可以完全机械地衍生出来Tree并且(我相信)任何以这种方式衍生的类型都是自动的Comonad,所以我觉得应该是这样我们可以通用和自动地构造这些类型及其组合.

实现拉链构造的一般性的一种方法是使用以下类和类型族

data Zipper t a = Zipper { diff :: D t a, here …
Run Code Online (Sandbox Code Playgroud)

haskell zipper deriving comonad

80
推荐指数
3
解决办法
5880
查看次数

Zipper用于创建xml请求?

如何创建XML符合XSD请求有效的请求?

一种方法是创建整个请求,然后在其上进行验证XSD.有没有办法在走模式时创建请求?

想到的第一个想法是Zipper,但我真的不确定它们是否可以在这里使用.

也许我还没有理解它,但如果已经定义了一些结构并且需要在该结构中进行更改,那么Zipper似乎很棒.Zipper可以用于改变结构吗?(例如,将序列附加到序列数组?)

xml haskell zipper

48
推荐指数
1
解决办法
866
查看次数

什么是Zipper数据结构,我应该使用它吗?

问题很简单:我无法理解Zipper数据结构.

我的问题与它在树上的用法有关.

我想了解如何使用zipper更改树节点.以及如何不复制整棵树(或大部分).

请澄清拉链是否有问题.也许它无法帮助树更新?
或者,也许,有可能更新树,我只是看不到路?

theory functional-programming zipper data-structures

46
推荐指数
3
解决办法
8039
查看次数

镜片和拉链有什么区别?

这是在Haskell中使用拉链的一个例子:

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 …
Run Code Online (Sandbox Code Playgroud)

haskell functional-programming clojure zipper haskell-lens

25
推荐指数
2
解决办法
3028
查看次数

Zipper类似于具有多个游标的数​​据结构

当人们想要遍历树并保持当前位置时,Zipper数据结构很棒,但是如果他们想要跟踪多个位置,应该使用哪种数据结构?

让我用例子解释一下:

  • #haskell频道上的某个人告诉我,在yi编辑器中使用拉链来表示光标位置.这很棒,但是如果你想要两个游标怎么办呢.就像你想要表示选择一样,你需要知道选择的开始和结束.
  • 在wikibooks的Minotaur示例中,他们使用Zipper来表示Minotaur在迷宫内的位置.如果我想将敌人添加到迷宫中,用拉链代表他们的位置就会有意义.
  • 最后一个实际上来自我的迷你项目,它开始了:作为学习Haskell的一部分,我正在尝试使用cairo和gth2hs可视化树结构.到目前为止,这已经很顺利,但现在我想选择一个或多个节点,并能够移动它们.因为可以有多个选定节点,所以我不能只使用教科书中定义的Zipper.

有一个简单的(幼稚?)解决方案,类似于他们在XMonad的早期版本中使用的涉及作为解释的有限的地图在这里.

也就是说,例如,在我的示例项目的情况下,我将所选节点存储在索引映射中,并用索引替换它们在主结构中的表示.但是这种解决方案有很多缺点.就像上面链接中解释的那样,或者说,在我的例子的情况下,取消选择所有节点将需要搜索整个树.

haskell functional-programming referential-transparency zipper data-structures

24
推荐指数
2
解决办法
1957
查看次数

二维拉链

最近关于Haskell中关于2d网格的问题的启发,我想知道是否有可能创建一个二维拉链来跟踪列表列表中的位置.列表中的一维拉链允许我们在大型列表中实际高效地移动本地(常见示例是文本编辑器).但是我们假设我们有这样的第二个维度:

grid = 
    [[ 1, 2, 3, 4, 5]
    ,[ 6, 7, 8, 9,10]
    ,[11,12,13,14,15]
    ,[16,17,18,19,20]
    ,[21,22,23,24,25]]
Run Code Online (Sandbox Code Playgroud)

我们是否可以创建某种拉链数据结构,不仅可以高效地左右移动,而且可以在网格中上下移动?如果是这样,如果我们用无限列表的无限列表替换列表列表,我们仍然可以获得有效的运动吗?

haskell functional-programming zipper multidimensional-array data-structures

23
推荐指数
2
解决办法
1764
查看次数

如何使二叉树拉链成为Comonad的一个实例?

我想把二叉树拉链作为comonad的一个实例,但我无法弄清楚如何duplicate正确实现.

这是我的尝试:

{-# LANGUAGE DeriveFunctor #-}
import Data.Function
import Control.Arrow
import Control.Comonad

data BinTree a
    = Leaf a
    | Branch a (BinTree a) (BinTree a)
      deriving (Functor, Show, Eq)

data Dir = L | R
    deriving (Show, Eq)

-- an incomplete binary tree, aka data context
data Partial a = Missing Dir (BinTree a) a
    deriving (Show, Eq, Functor)

-- BTZ for BinTree Zipper
newtype BTZ a = BTZ { getBTZ :: ([Partial a], BinTree a) }
    deriving …
Run Code Online (Sandbox Code Playgroud)

haskell zipper comonad

23
推荐指数
1
解决办法
1683
查看次数

Monad都是可区分的类型

鉴于可区分的类型,我们知道Zipper是一个Comonad.对此,Dan Burton问道,"如果衍生产生了一个共同点,这是否意味着整合会产生一个单子?或者这是无意义的?".我想给这个问题一个特定的含义.如果类型是可区​​分的,它是否必然是monad?考虑到以下定义,问题的一个表述是要问

data Zipper t a = Zipper { diff :: D t a, here :: a }

deriving instance Diff t => Functor (Zipper t)

class (Functor t, Functor (D t)) => Diff t where
    type D t :: * -> *
    up :: Zipper t a -> t a
    down :: t a -> t (Zipper t a)
Run Code Online (Sandbox Code Playgroud)

我们可以编写类似于签名的函数吗?

return :: (Diff t) => a -> t a
(>>=) …
Run Code Online (Sandbox Code Playgroud)

monads haskell zipper deriving

19
推荐指数
1
解决办法
457
查看次数