2010-03-21 6 views
8

Je suis un débutant absolu dans Haskell essayant pourtant de comprendre comment cela fonctionne.Haskell, la liste du nombre naturel

Je veux écrire ma propre liste paresseuse d'entiers tels que [1,2,3,4,5 ...].

Pour la liste des ceux que j'ai écrit

ones = 1 : ones 

et quand essayé, fonctionne très bien:

*Main> take 10 ones 
[1,1,1,1,1,1,1,1,1,1] 

Comment puis-je faire la même chose pour les entiers de plus en plus?

J'ai essayé mais il échoue en effet:

int = 1 : head[ int + 1] 

Et après cela comment puis-je faire une méthode qui multiplie deux cours d'eau? tels que:

mulstream s1 s2 = head[s1] * head[s2] : mulstream [tail s1] [tail s2] 
+1

Vous pourriez être confus au sujet de la différence entre() et [], puisque votre dernier exemple fonctionne (pour les listes infinies) si vous remplacez tous les [] par(). –

Répondre

17

Les raisons qui int = 1 : head [ int + 1] ne fonctionne pas sont:

  • tête retourne un seul élément, mais le second argument : doit être une liste.
  • int + 1 essaie d'ajouter une liste et un nombre, ce qui n'est pas possible.

La meilleure façon de créer la liste de comptage de 1 à l'infini est [1..]

Pour compter dans d'autres étapes que vous pouvez utiliser 1 [firstElement, secondElement ..], par exemple pour créer une liste de tous les entiers impairs positifs: [1, 3 ..]

Pour obtenir des listes infinies de la forme [x, f x, f (f x), f (f (f x)),...], vous pouvez utiliser iterate f x, par exemple. iterate (*2) 1 renverra la liste [1, 2, 4, 16,...].

Pour appliquer une paire d'opération sur chaque paire d'éléments de deux listes, utilisez zipWith:

mulstream s1 s2 = zipWith (*) s1 s2 

Pour rendre cette définition plus concise, vous pouvez utiliser le formulaire sans le point:

mulstream = zipWith (*) 
11

pour les nombres naturels que vous devez utiliser la carte:

num1 = 1 : map (+1) num1 

Ou compréhensions:

num2 = 1 : [x+1 | x <- num2] 

Ou bien sûr:

num3 = [1..] 
+3

ou aussi 'nat = 1: carte succ nat' – sastanin

2

Il y a syntaxe pour cela dans le langauge:

take 10 [1,2..] 

=> [1,2,3,4,5,6,7,8,9,10] 

Vous pouvez même faire différents progrès:

take 10 [1,3..] 
=> [1,3,5,7,9,11,13,15,17,19] 
3

Je Je ne sais pas si c'est ce que vous demandiez, mais il me semble que vous vouliez pour construire une liste de nombres naturels croissants, sans compter sur aucune autre liste. Ainsi, par ce jeton, vous pouvez faire des choses comme

incr a = a : inrc (a+1) 
lst = inrc 1 

take 3 lst 
=> [1,2,3] 

que, techniquement, est appelée une fonction d'accumulation (je crois) et tout ce que nous avons est de faire un cas particulier de facilement utilisable avec « LST »

vous pouvez fou à partir de là, faire des choses comme:

lst = 1 : incr lst where incr a = (head a) + 1 : incr (tail a) 

take 3 lst 
=> [1,2,3] 

et ainsi de suite, mais qui repose probablement sur des choses que vous avez l'habitude encore appris (où) - à en juger par l'OP - mais il devrait lis toujours assez facilement.

Oh, à droite, puis la multiplication de la liste. Eh bien, vous pouvez utiliser zipWith (*) comme mentionné ci-dessus, ou vous pouvez réinventer la roue comme ça (il est plus amusant, croyez-moi :)

lmul a b = (head a * head b) : lmul (tail a) (tail b) 
safemul a b = take (minimum [len a, len b]) (lmul a b) 

La raison safemul, je crois, vous trouverez par expérimenter avec la fonction, mais il doit faire avec «queue». Le problème est qu'il n'y a pas de cas pour une liste vide, des listes incompatibles, et ainsi de suite, donc vous devrez soit pirater différentes définitions (lmul _ [] = []) ou utiliser des gardes et ou où et ainsi de suite ... ou coller avec zipWith :)