2016-02-06 4 views
7

Я читаю учебник learn you a haskell и Я пробовал некоторые примеры, приведенные автором .Haskell Pattern Matching: удобочитаемость и производительность

Например, он переопределен почтовый индекс следующим образом:

zip' :: [a] -> [b] -> [(a,b)] 
zip' _ [] = [] 
zip' [] _ = [] 
zip' (x:xs) (y:ys) = (x,y):zip' xs ys 

Он использует подобный подход для всех его других примеров, , где он ставит самые конкретные образцы первой. Вот немного отличается версии функции почтового индекса:

zip' :: [a] -> [b] -> [(a,b)] 
zip' (x:xs) (y:ys) = (x, y):zip' xs ys 
zip' _ _   = [] 

Насколько я понимаю, оба метода делает то же самое. Если предоставляется пустой список в любом направлении (x: xs) или (y: ys), не будет соответствовать, который завершит рекурсию, добавив пустым списком [].

  1. Я лично предпочитаю вторую версию для удобочитаемости, но, возможно, я ошибаюсь в этом.
  2. Оказывает ли это какое-либо влияние на эффективность метода? Насколько я понимаю, если самый верхний шаблон не соответствует, Haskell будет проверять следующий шаблон. Оказывает ли порядок паттернов влиянию на производительность?

С наилучшими пожеланиями,

Edit:

Возможно дубликата: Haskell GHC: what is the time complexity of a pattern match with N constructors?

Резюме: Порядок моделей очень важно для семантики (с точки зрения строгой оценки аргументов) и читаемость функции. Совпадение шаблона всегда будет в O (1) сложность времени.

+0

Возможный дубликат [Haskell GHC: какова временная сложность совпадения шаблонов с конструкторами N?] (Http://stackoverflow.com/questions/9027384/haskell-ghc-what-is-the-time-complexity -of-a-pattern-match-with-n-constructors) – Nimi

ответ

7

Насколько я понимаю, оба метода делают то же самое.

почти; с исключением:

\> zip' undefined [] -- 1st definition of zip' 
[] 
\> zip' (filter (< 4) [1..]) [1, 2, 3] 
[(1,1),(2,2),(3,3)] 

тогда:

\> zip' undefined [] -- 2nd definition of zip' 
*** Exception: Prelude.undefined 
\> zip' (filter (< 4) [1..]) [1, 2, 3] 
[(1,1),(2,2),(3,3) -- gets stuck here; never returns 

другими словами, второе определение всегда заставляет weak head normal form для как аргументы.

Потенциально, это означает, что можно построить такой патологический пример, что WHNF включает в себя тяжелые вычисления, поэтому одно определение выполняется очень по-другому, чем другое.

+3

Это верно. Но 'zip 'undefined [1, 2, 3]' создаст исключение в обоих случаях. Поэтому я не вижу, как это помогает или, вернее, почему это было бы желательно. – Nimi

+1

@Nimi, в этом случае он определяет только *, который * аргумент безусловный. – dfeuer

+1

@ Суть в том, что вы можете заставить две функции вести себя по-разному, а не делать то же самое. обратите внимание на другой пример: 'zip '(filter (<4) [1 ..]) [1, 2, 3]', чтобы увидеть, как это может также повлиять на производительность. –