Рекомендуется всегда иметь исчерпывающие соответствия шаблона в Haskell, даже для “невозможных” случаев?

scandir порядки по возрастанию или убыванию в алфавитном порядке. Но вы хотите отсортировать по дате последнего изменения. Так что вам нужно применить функцию сортировки к нему. Например, вы можете сделать это с помощью filemtime и uasort

$items = glob ...
uasort($items, function($a,$b) { return filemtime($a) > filemtime($b); })

Отразить filemtime($a) > filemtime($b) в filemtime($a) < filemtime($b) для asc / desc http://php.net/manual/en/function.scandir.php#refsect1-function.scandir-parameters

17
задан Charlie Flowers 7 May 2009 в 05:20
поделиться

5 ответов

Вероятно, это скорее вопрос стиля, чем что-либо еще. Лично я бы поставил

_ -> error "Impossible! Empty list in step"

, лишь бы отключить предупреждение :)

20
ответ дан 30 November 2019 в 10:54
поделиться

Чтобы прокомментировать мой предыдущий комментарий, я понял, что есть способ подтвердить пропущенный случай, но все же получить полезную ошибку с номером файла / строки. Однако он не идеален, так как будет отображаться только в неоптимизированных сборках (см. здесь ).

...
[]:xs -> assert False (error "unreachable because I know everything")
4
ответ дан 30 November 2019 в 10:54
поделиться

В этом особом случае вы можете устранить предупреждение, выполнив следующие действия:

gb_groupBy p input = foldr step [] input
   where
     step item acc = case acc of
        []                           -> [[item]]
        (xs:xss)                      -> if p (head xs) item
                                         then  (item:xs):xss
                                         else [item]:acc

Сопоставление с образцом завершено, и «невозможное» условие пустого списка в заголовке аккумулятора будет вызывают ошибку времени выполнения, но не предупреждают.

Другой способ взглянуть на более общую проблему неполных сопоставлений с образцом - рассматривать их как «запах кода», то есть признак того, что мы пытаемся решить проблему неоптимальным образом. , или не-Haskellish, способом, и попробуйте переписать наши функции.

Реализация groupBy с помощью foldr делает невозможным применение его к бесконечному списку, что является целью разработки, которую функции Haskell List пытаются достичь везде, где семантически разумно , Рассмотрим

take 5 $ groupBy (==) someFunctionDerivingAnInfiniteList

Если первые 5 групп относительно равенства конечны, ленивое вычисление прекратится. Это то, что ты можешь » Не делайте этого на строго оцененном языке. Даже если вы не работаете с бесконечными списками, написание таких функций даст лучшую производительность для длинных списков или позволит избежать переполнения стека, которое происходит при оценке выражений типа

take 5 $ gb_groupBy (==) [1..1000000]

В List.hs groupBy равно реализовано следующим образом:

groupBy         :: (a -> a -> Bool) -> [a] -> [[a]]
groupBy _  []       =  []
groupBy eq (x:xs)   =  (x:ys) : groupBy eq zs
                           where (ys,zs) = span (eq x) xs

Это позволяет интерпретатору / компилятору оценивать только те части вычисления, которые необходимы для получения результата. span дает пару списков, где первый состоит из (последовательных) элементов из заголовка списка, удовлетворяющих предикату, а второй - остальная часть списка. Он также реализован для работы с бесконечными списками.

11
ответ дан 30 November 2019 в 10:54
поделиться

Я считаю, что проверка полноты по шаблонам случаев обязательна. Я стараюсь никогда не использовать _ в случае на верхнем уровне, потому что _ соответствует всему, и, используя его, вы подрываете ценность проверки полноты. Это менее важно для списков, но критически важно для определяемых пользователем алгебраических типов данных, потому что я хочу иметь возможность добавить новый конструктор и отключить компилятор для всех отсутствующих случаев. По этой причине я всегда компилирую с включенным -Werror , поэтому я не могу исключить случай.

Как уже отмечалось, ваш код может быть расширен с помощью этого случая

[] : _ -> error "this can't happen"

Внутренне, GHC имеет функцию паники , которая, в отличие от error , выдает координаты источника, но я посмотрел на реализацию и не смог понять ее.

9
ответ дан 30 November 2019 в 10:54
поделиться

Система типа - ваш друг, и предупреждение о том, чтобы вы знали, что ваша функция имеет трещины. Очень лучший подход - пойти на более чистый, более элегантный посадку между типами.

Рассмотрим определение ГКГ Groupby :

groupBy                 :: (a -> a -> Bool) -> [a] -> [[a]]
groupBy _  []           =  []
groupBy eq (x:xs)       =  (x:ys) : groupBy eq zs
                           where (ys,zs) = span (eq x) xs
2
ответ дан 30 November 2019 в 10:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: