deniok: (lambda cube)
[personal profile] deniok
Хорошая хотя и простая задачка возникла в процессе проверки домашних заданий. Чем отличается поведение следующих двух функций, и в чем причина такого отличия:
diff xs = do
    p <- zip xs (tail xs)
    return $ abs (fst p - snd p)

diff' xs = do
    p <- zip (tail xs) xs
    return $ abs (fst p - snd p)

Date: 2014-04-15 06:29 am (UTC)
From: [identity profile] thedeemon.livejournal.com
Полагаю, разница в порядке попыток вычисления первого элемента списка и наличия второго. Если передать список из одной задницы, то в одном случае получится задница, во втором исключение. Мораль: нетотальные языки - пустая трата времени. :)

Date: 2014-04-15 06:59 am (UTC)
From: [identity profile] zelych.livejournal.com
Симпатичная загадка.

Разница в том, что diff' [] вычисляет сначала tail [] и отваливается с ошибкой.
Т.е. у zip только второй аргумент лениво вычисляется.
Edited Date: 2014-04-15 07:00 am (UTC)

Date: 2014-04-15 02:56 pm (UTC)
From: [identity profile] deni-ok.livejournal.com
Дело не конкретно в zip, zip-то можно сфэйлить и на втором аргументе
> (\xs -> zip xs (tail $ tail xs)) [42]
*** Exception: Prelude.tail: empty list
Дело в том, что сопоставление с образцом всегда делается сверху вниз (по уравнениям) и слева направо (по образцам-параметрам текущего уравнения). Поэтому, если первый в текущем уравнении образец представлен конструктором, то для сопоставления соответствующий параметр передаваемый в функцию должен быть приведен в WHNF. А у zip оказывается так, что если WHNF - это пустой список, то выбирается второе уравнение, которому пофиг на второй аргумент.

Date: 2014-04-15 03:49 pm (UTC)
From: [identity profile] zelych.livejournal.com
Ага, спасибо за пояснения.

Т.е. (если я правильно пользуюсь терминами) zip всегда строгий по первому агрументу, и иногда не строгий по второму. А сопоставление с образцом -- это причина строгости/нестрогости.

Date: 2014-04-15 05:27 pm (UTC)
From: [identity profile] deni-ok.livejournal.com
Мне не очень нравится термин "строгий" по отношению к функциям с богатой семантикой. Он слишком грубо описывает действительность. Ну вот сделаю я обычную take более определенной, чем в Prelude, переставив местами два первых уравнения:
take' _ []              =  []
take' n _      | n <= 0 =  []
take' n (x:xs)          =  x : take' (n-1) xs
Раньше take была строгая по первому аргументу, а стала "иногда нестрогая":
> take undefined []
*** Exception: Prelude.undefined
> take' undefined []
[]
Но понятно, что это же совершенно маргинальное улучшение!

Date: 2014-04-15 09:28 am (UTC)
From: [identity profile] udpn.livejournal.com
>> нетотальные языки - пустая трата времени

А нетотальные языки это вообще языки?

Date: 2014-04-15 10:03 am (UTC)
From: [identity profile] thedeemon.livejournal.com
Конечно. По Хомскому, даже Go - язык.

Profile

deniok: (Default)
deniok

February 2022

S M T W T F S
  12345
6789101112
13141516171819
20212223 242526
2728     

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Jul. 23rd, 2025 02:07 am
Powered by Dreamwidth Studios