Реализуйте функции отмены и повтора, используя стек.Как редактировать стек без необходимости воссоздавать его в Haskell - PullRequest
2 голосов
/ 01 апреля 2019

У меня есть собственный тип данных с именем 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, как создать стек как структуру, не дублируя его?

1 Ответ

7 голосов
/ 01 апреля 2019

как создать стек как структуру, не дублируя его?

Код, представленный вами, в порядке и не будет дублировать большие объемы данных.

Допустим,у вас текущий стек 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
...