2

我有一个名为 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 中更改变量的值,你如何在不复制堆栈的情况下创建一个结构?

4

1 回答 1

7

如何在不复制堆栈的情况下将堆栈创建为结构?

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

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

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

您将返回一个新堆栈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。如果stack1并且stack2仍然存在,那么堆看起来像:

     stack3 -> z
               |
 stack1 -> a - b - c - d - e
               ^
               |
             stack2
于 2019-04-01T14:42:01.443 回答