#haskell #types #implementation #deque
#haskell #типы #реализация #deque
Вопрос:
как написать в Haskell очередь с двойным завершением («deque»). Структура данных должна иметь функции emptyDeque, front, back, removeFront, removeBack, addFront, addBack и isEmpty, а затем отображать двустороннюю очередь между -> и <- .
это то же самое, но для очереди:
module Queues (Queue, emptyQueue, front, remove, add, isEmpty)
newtype Queue a = Queue [a]
emptyQueue = Queue []
front (Queue (x:xs)) = x
front (Queue []) = error("No front of empty queue")
add (Queue xs) x = Queue (xs [x])
remove (Queue (x:xs)) = Queue xs
remove (Queue []) = error("Nothing on queue to remove")
isEmpty (Queue []) = True
isEmpty (Queue (x:xs)) = False
showElems [] = ""
showElems (x:xs) = " " (Prelude.show x) (showElems xs)
showQueue (Queue a) = "<" (showElems a) " >"
instance (Show a) => Show (Queue a) where show = showQueue
Я придумал, правильно ли это?
module Deques (Deque, emptyDeque, front, back, removeFront, removeBack , addFront, addBack, isEmpty)
newtype Deque a = Deque [a]
emptyQueue = Queue []
reverses (x:xs) = (reverses xs) [x]
front (Deque (x:xs)) = x
front (Deque []) = error("No front of empty Deque")
back (Deque a) = front(reverse(a))
back (Deque []) = error("No back of empty Deque")
addBack (Deque xs) x = Deque (xs [x])
addFront (Deque xs) x = Deque ([x] xs)
removeFront (Deque (x:xs)) = Deque xs
removeFront (Deque []) = error("Nothing on Deque to remove")
removeBack (Deque a) = reverses(removeFront(reverses(a))
`
Комментарии:
1. Проверьте пакет «deque» в Hackage или прочитайте статью Криса Окасаки » Простые и эффективные чисто функциональные очереди и запросы
2. да, это так, я пытался создать очередь, думая, что с этого было бы проще начать. разве deque не то же самое, что очередь, но с добавлением: back, add back removeback.
3. Попробуйте сохранить два списка, один для начала, а другой для конца. Или просто прочитайте статью Окасаки.
4. @biz: Если вы только что запустили Haskell, то они, вероятно, не ожидают, что вы знаете Okasaki. Ваш
back
выглядит нормально. ВашaddFront
работает (и эффективно), но нет необходимости создавать и объединять список спереди; вы можете просто использовать:
.5. хорошая составная реализация
removeBack
. Я поражен тем, сколько программистов не используют повторно свой собственный код. Продолжайте так думать 🙂
Ответ №1:
Использование списков для реализации Deque не очень эффективно, но это может сработать. Несколько замечаний
Помимо ошибок типа, вы, похоже, пишете приложение-функцию в стиле других языков
front(reverse(a))
В Haskell скобки предназначены просто для группировки. Более простой способ написания этой строки был бы
front (reverse a)
или даже
front $ reverse a
Еще одно замечание: добавление чего-либо в начало списка очень типично в Haskell
[x] xs -- The weird way
x : xs -- The canonical way
Однако добавление в конец списка — это некрасиво.
xs [x] -- No better way for normal lists. This is inefficient
У вас довольно хорошее начало, но вам следует попытаться ознакомиться с уникальной парадигмой и стилем Haskell. Первые несколько глав Learn You a Haskell хорошо справляются с этой задачей.
Ответ №2:
На самом деле вот моя окончательная реализация Deque, которая отлично работает
module Deques (Deque, emptyDeque, front, back, removeFront, removeBack, addFront, addBack, isEmpty) where
newtype Deque a = Deque [a]
backwards (Deque []) = Deque []
backwards (Deque a) = Deque( reverse a )
emptyDeque = Deque []
front (Deque (x:xs)) = x
front (Deque []) = error("No front of empty Deque")
back (Deque a) = front( backwards (Deque a))
back (Deque []) = error("No back of empty Deque")
addBack (Deque xs) x = Deque (xs [x])
addFront (Deque xs) x = Deque (x : xs)
removeFront (Deque (x:xs)) = Deque xs
removeFront (Deque []) = error("Nothing on Deque to remove")
removeBack (Deque a) = backwards( removeFront( backwards (Deque a) ))
removeBack (Deque []) = error("Nothing on Deque to remove")
isEmpty (Deque []) = True
isEmpty (Deque (x:xs)) = False
showElems [] = ""
showElems (x:xs) = " " (Prelude.show x) (showElems xs)
showDeque (Deque a) = "<" (showElems a) " >"
instance (Show a) => Show (Deque a) where show = showDeque
Комментарии:
1. addBack равен O (n), поэтому создание большого Deque путем многократного добавления к обратной стороне равно O (n ^ 2). Я думаю, это нормально, если вы никогда этого не сделаете, но тогда в чем смысл Deque?