Haskell, список натуральных чисел
я абсолютный новичок в Haskell, но пытаюсь понять, как это работает.
Я хочу написать свой собственный ленивый список целых чисел, таких как [1,2,3,4,5...].
для списка тех, которые я написал
ones = 1 : ones
и при попытке, работает нормально:
*Main> take 10 ones
[1,1,1,1,1,1,1,1,1,1]
как я могу сделать то же самое для увеличения чисел ?
Я пробовал это, но это действительно удается:
int = 1 : head[ int + 1]
и после этого как я могу сделать метод, который умножает два ручьи? например:
mulstream s1 s2 = head[s1] * head[s2] : mulstream [tail s1] [tail s2]
4 ответов
причины int = 1 : head [ int + 1]
не работает:
- head возвращает один элемент, но второй аргумент
:
нужно список. -
int + 1
пытается добавить список и число, что невозможно.
самый простой способ создать список подсчета от 1 до бесконечности -[1..]
в Этап 1 Вы можете использовать [firstElement, secondElement ..]
, например, для создания списка всех положительных нечетных чисел: [1, 3 ..]
чтобы получить бесконечные списки вида [x, f x, f (f x), f (f (f x)),...]
можно использовать iterate f x
, например,iterate (*2) 1
возвращает список [1, 2, 4, 16,...]
.
чтобы применить операцию попарно к каждой паре элементов из двух списков, используйте zipWith:
mulstream s1 s2 = zipWith (*) s1 s2
чтобы сделать это определение более емким можно использовать в свободной форме:
mulstream = zipWith (*)
для натуральных чисел вы должны использовать map:
num1 = 1 : map (+1) num1
или пониманий:
num2 = 1 : [x+1 | x <- num2]
или же:
num3 = [1..]
Я не уверен, что это то, о чем вы спрашивали, но мне кажется, что вы хотели построить список возрастающих натуральных чисел, не полагаясь на какой-либо другой список. Таким образом, вы можете делать такие вещи, как
incr a = a : inrc (a+1)
lst = inrc 1
take 3 lst
=> [1,2,3]
это, технически, называется аккумулирующей функцией (я считаю), и тогда все, что мы сделали, это сделать особый случай его легко использовать с "lst"
вы можете сойти с ума оттуда, делая такие вещи, как:
lst = 1 : incr lst where incr a = (head a) + 1 : incr (tail a)
take 3 lst
=> [1,2,3]
и так далее, хотя это, вероятно, зависит от некоторых вещей, которые вы еще не узнали (где) - судя по OP - но он все равно должен читать довольно легко.
о, правильно, а затем умножение списка. Ну, вы можете использовать zipWith ( * ), как упоминалось выше, или вы можете изобрести колесо, как это (это веселее, поверьте мне:)
lmul a b = (head a * head b) : lmul (tail a) (tail b)
safemul a b = take (minimum [len a, len b]) (lmul a b)
причину safemul, я полагаю, вы можете узнать, экспериментируя с функцией, но это связано с "хвостом". Беда в том, что для этого нет оснований. пустой список, несовпадающие списки, и так далее, так что вы либо будете иметь, чтобы взломать вместе различные определения (lmul _ [] = []) или использовать охранников и или где и так далее ... или придерживайтесь zipWith:)
существует синтаксис для этого в langauge:
take 10 [1,2..]
=> [1,2,3,4,5,6,7,8,9,10]
вы даже можете делать разные шаги:
take 10 [1,3..]
=> [1,3,5,7,9,11,13,15,17,19]