Я реализую фильтр в Haskell, то есть программу, которую я могу вызвать из командной строки следующим образом:
$ cat inputfile.txt | myFilter > outputfile.txt
При запуске программы в файле размером около 80 МБ я получаю переполнение стека (Переполнение пространства стека: текущий размер 8388608 байт.). Я использую GHC Version 6.12.3 под cygwin.
Я думаю, проблема связана с функцией sort
, которую я использую в программе, но после того, как я искал проблему в течение трех дней, я не знаю, как это решить, поэтому я хотел бы, чтобы кто-то мог дать мне подсказка.
Вот основные сведения о моей программе.
Моя программа фильтрации считывает стандартный ввод в строку, разбивает ее на строки и анализирует каждую строку в записи какого-либо типа Event
data Event = ...
который является экземпляром Ord
instance Ord Event where
x < y = ...
чтобы я мог сортировать события, используя встроенную функцию sort
.
Разделение на строки и разбор событий (по одному событию на строку) выполняется функцией
p :: String -> [Event]
который внутренне использует стандартную функцию lines
.
У меня также есть функция g, которая группирует события:
g :: [Event] -> [[Event]]
g использует некоторые критерии, которые здесь не актуальны; каждая группа может содержать не более 4 событий.
Я сортирую каждую группу событий (представленную как список) с помощью sort
(т.е. все события внутри каждой группы сортируются) и, наконец, отформатирует все группы событий как строку с помощью функции
f :: [[Event]] -> String
Основная функция выглядит следующим образом:
main = interact (f . (map sort) . g . p)
Как сказано, запуск этой программы в файле размером около 80 МБ приводит к переполнению стека.
Если я заменил функцию сортировки следующей функцией (наивная быстрая сортировка):
mySort :: [Event] -> [Event]
mySort [] = []
mySort (e:es) = let h = [j | j <- es, j < e]
t = [j | j <- es, e < j]
in
(mySort h) ++ [e] ++ (mySort t)
main = interact (f . (map mySort) . g . p)
У меня нет!
Если в функции mySort
я заменю определение t
следующим образом:
t = [j | j <- es, e <= j]
то есть. Я заменяю <
на <=
, переполнение стека снова!
Итак, я не знаю, что здесь происходит.
Я не вижу, что я ввел бесконечную рекурсию. Моя другая гипотеза заключается в том, что здесь может играть роль ленивая оценка (<=
производит более сильный удар, чем <
?).
У меня есть некоторый опыт работы с Haskell, но я не настоящий эксперт, поэтому я был бы рад получить полезный намек, потому что я изо всех сил пытался понять это в течение последних трех дней.