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

Wil*_*uff 2 stack haskell undo redo

我有一个名为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)
Run Code Online (Sandbox Code Playgroud)

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

Tho*_*son 7

如何将堆栈创建为结构而不进行复制?

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

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

pop (Stack (x:xs)) = (Just x, Stack xs)
Run Code Online (Sandbox Code Playgroud)

您将返回一个新的堆栈stack2 = b - c - d - e,该堆栈只是a复制后的整个结构,不会复制任何内容。如果保持stack1左右,那么您将拥有两个看起来像这样的结构:

 stack1 -> a - b - c - d - e
               ^
               |
             stack2
Run Code Online (Sandbox Code Playgroud)

请记住,您所使用的单链接列表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
Run Code Online (Sandbox Code Playgroud)