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]