Язык Haskell: О пользе и вреде лени: различия между версиями

Перейти к навигации Перейти к поиску
нет описания правки
Нет описания правки
Нет описания правки
Введём следующие определения.
 
<code>toDigtstoDigits :: Integer -&gt; [Integer]
toDigtstoDigits n | n == 0 = []
| otherwise = (n `mod` 2) : toDigits (n `div` 2)
countUnits = sum . toDigits
 
<code>powers = map (2 ^ ) [0..]
toPowers' = zipWith (*) powers . toDigsItoDigits</code>
 
Вообще <code>zipWith (*) [<math>a_1, a_2, a_3, \dots</math>] [<math>b_1,b_2,b_3,\dots</math>]</code> равно <code>[<math>a_1*b_1, a_2*b_2, \dots</math>]</code>, где вместо звёздочки может стоять произвольная операция. В частности, <code>zipWith (+) [1, 2, 3] [10, 100, 1000]</code> даст в результате <code>[11, 102, 1003]</code>. В итоге имеем
— первый способ:
 
<code>toPowers = filter (/=0) . zipWith (*) powers . toDigsItoDigits</code>
 
Функция <code>filter</code> получает на вход булеву функцию (функцию, возвращающую «правду» или «ложь») и список, а возвращает список только из тех элементов, на которых значение этой функции равно «правде». В данном случае мы оставляем только ненулевые элементы:
<code>toPowers (16 + 8 + 1) <math>\Rightarrow</math> [1, 8, 16]</code>.
 
Функция <code>zipWith</code> получает три аргумента. Если указано только два аргумента, то она превращается в функцию от одного аргумента. Это позволяет использовать выражение <code>zipWith (*) powers</code> как функцию от одного аргумента и поместить в цепочку композиции с функцией <code>toDigsItoDigits</code>. Аналогичная ситуация с функцией <code>filter</code>: мы задали для неё первый аргумент — <code>(/=0)</code> — это функция сравнения с нулём. Второй аргумент остался неопределённым. Он достанется ей по цепочке как значение
функции <code>zipWith (*) powers</code> на том, что вернёт ей функция <code>toDigsItoDigits</code>, применённая к тому, что даст пользователь в качестве аргумента функции <code>toPowers</code>.
 
Точки в определении функции <code>toPowers</code> играют роль операции «|» (pipe) в стандартной оболочке Linux. С помощью этой операции происходит передача результатов вычисления одной функции на вход другой. В нашем случае была выстроена цепочка из трёх функций.
— второй способ:
 
<code>toPowers = \n -&gt; filter (/= 0) (zipWith (*) powers (toDigsItoDigits n))</code>
 
— третий способ:
 
<code>toPowers n = filter (/= 0) (zipWith (*) powers (toDigsItoDigits n))</code>
 
В этих способах мы явно вводим аргумент <code>n</code> и используем его в выражении, и скобки располагаем уже совсем другим образом.
Анонимный участник

Навигация