使用堆栈实现撤消和重做功能。如何编辑堆栈而不必在 Haskell 中重新创建它

Implement undo and redo functions using a stack. How to edit a stack without having to recreate it in Haskell

我有一个名为 TextFile 的自定义数据类型,它存储四个字符串,每次编辑文本文件时我都需要能够将它的一个版本存储在堆栈中。这样我就可以实现某种形式的撤消和重做功能。

但是,堆栈将从其他函数中更新,并且每次都不会创建新堆栈,我无法在向堆栈推送内容时保存更改?

有没有一种方法可以创建一个堆栈并在每次从堆栈中推入或弹出某些内容时更新同一个堆栈?

newtype Stack a = Stack [a] deriving (Eq, Show)
buffer = Stack [] :: Stack TextFile

data TextFile = TextFile String String String String deriving Show
file = TextFile "This is the left element" " This is the right element" "" ""

pop :: Stack a -> (Maybe a, Stack a)
pop (Stack (x:xs)) = (Just x, Stack xs)
pop (Stack []) = (Nothing, Stack [])

push :: a -> Stack a -> Stack a
push x (Stack xs) = Stack (x:xs)

澄清一下,我的主要问题是如果您不能更改 Haskell 中的变量值,您如何在不复制它的情况下将堆栈创建为结构?

how do you create a stack as a structure without duplicating it?

您提供的代码很好,不会重复太多数据。

假设您当前有 stack1 = a - b - c - d - e 个堆栈。现在您 pop stack1 使用代码:

pop (Stack (x:xs)) = (Just x, Stack xs)

您将 return 一个新堆栈 stack2 = b - c - d - e,它只是 a 之后的整个结构,没有任何内容被复制。如果你保留 stack1 那么你会有两个看起来像这样的结构:

 stack1 -> a - b - c - d - e
               ^
               |
             stack2

请记住,您使用的单链表意味着 a 不是 stack2 的一部分。如果 stack1 被垃圾回收,那么您最终会得到 stack2 = b - c - d - e,如您所料。

现在假设你 push z stack2 屈服 stack3 = z - b - c - d - e。如果 stack1stack2 仍然存在,那么堆将类似于:

     stack3 -> z
               |
 stack1 -> a - b - c - d - e
               ^
               |
             stack2