мне интересно, когда пакет»вызывается в первом охранником
x == head h_p_xs
охранником заставляет оценку h_p_xs
, которая вызывает рекурсивный вызов.
и если это общий шаблон в Haskell кода для ссылки на голову и хвост списка вернулся из вызова функции.
Я думаю, что это довольно распространенный образец. Вы также можете найти варианты, используя вместо этого case pack' xs of ...
или let ... = pack' xs in ...
.Обратите внимание, что использование let
или where
с таким шаблоном, как h_p_xs:t_p_xs
, приведет к ошибке выполнения во время нахождения пустого списка. Этот код осторожен, чтобы рекурсивный вызов не возвращал список emlty.
Есть несколько вызовов, чтобы упаковать» на любых уровнях рекурсии
Чтобы быть педантичным, стандарт Haskell не определяет, как код на самом деле оценивается, но только то, что является результатом. Итак, теоретически, компилятору разрешено делать любое количество рекурсивных вызовов.
Прагматично, компиляторы будут осторожны, чтобы сделать только один рекурсивный вызов - это не приведет к ужасному исполнению.
Для сравнения, ниже код эквивалентен, но привел бы к экспоненциальным сложности (!)
...
where p_xs = h_p_xs:t_p_hs
h_p_xs = head (pack' xs)
t_p_xs = tail (pack' xs)
Здесь вы можете ожидать, что компилятор сделать два рекурсивных вызовы.
И это быстрое решение?
Да. Ожидается, что он будет работать в линейном времени на входе.
если я изменяю x == head h_p_xs = (x: h_p_xs): t_p_hs в x == head xs = (x: h_p_xs): t_p_hs есть разница в том, как работает программа? –
@ Þóróðinsson Это должно быть эквивалентно, насколько я могу видеть сейчас. – chi