说我有以下两个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)来更新这样的嵌套结构?
这是对我上一个问题的答案的后续跟进.
假设我需要映射每个项目a:A的List[A]来b:B使用功能def f(a:A, leftNeighbors:List[A]): B和产生List[B].
显然,我不能只是map在列表上调用,但我可以使用列表拉链.拉链是一个在列表中移动的光标.它提供对当前element(focus)及其邻居的访问.
现在我可以替换我f的 def 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]这就是为什么List是Monad和Zipper是Comonad.
是否有意义 ?
给定任何容器类型,我们可以形成(以元素为中心的)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)
这是一个情况Zip是Comonad,虽然它的实例的建设是一个有点毛.也就是说,Zip可以完全机械地衍生出来Tree并且(我相信)任何以这种方式衍生的类型都是自动的Comonad,所以我觉得应该是这样我们可以通用和自动地构造这些类型及其组合.
实现拉链构造的一般性的一种方法是使用以下类和类型族
data Zipper t a = Zipper { diff :: D t a, here …Run Code Online (Sandbox Code Playgroud) 如何创建XML符合XSD请求有效的请求?
一种方法是创建整个请求,然后在其上进行验证XSD.有没有办法在走模式时创建请求?
想到的第一个想法是Zipper,但我真的不确定它们是否可以在这里使用.
也许我还没有理解它,但如果已经定义了一些结构并且需要在该结构中进行更改,那么Zipper似乎很棒.Zipper可以用于改变结构吗?(例如,将序列附加到序列数组?)
问题很简单:我无法理解Zipper数据结构.
我的问题与它在树上的用法有关.
我想了解如何使用zipper更改树节点.以及如何不复制整棵树(或大部分).
请澄清拉链是否有问题.也许它无法帮助树更新?
或者,也许,有可能更新树,我只是看不到路?
这是在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) 当人们想要遍历树并保持当前位置时,Zipper数据结构很棒,但是如果他们想要跟踪多个位置,应该使用哪种数据结构?
让我用例子解释一下:
有一个简单的(幼稚?)解决方案,类似于他们在XMonad的早期版本中使用的涉及作为解释的有限的地图在这里.
也就是说,例如,在我的示例项目的情况下,我将所选节点存储在索引映射中,并用索引替换它们在主结构中的表示.但是这种解决方案有很多缺点.就像上面链接中解释的那样,或者说,在我的例子的情况下,取消选择所有节点将需要搜索整个树.
haskell functional-programming referential-transparency zipper data-structures
最近关于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
我想把二叉树拉链作为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) 鉴于可区分的类型,我们知道它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)