2009-02-10 9 views
4

J'essaye de créer une séquence paresseusement en utilisant F #.Seq.unfold explication in F #

La séquence est définie comme suit:

Le nième terme de la séquence de nombres triangle est donnée par, tn = ½n (n + 1); de sorte que les dix premiers numéros triangle sont:

1, 3, 6, 10, 15, 21, 28, 36, 45, 55, ...

Voici ce que j'ai à ce jour mais il dosnt semblent fonctionner:

let tri_seq = 1.0 |> Seq.unfold (fun x -> match x with           
              | _ -> Some (x, 0.5*x*(x + 1.0))) 

Merci beaucoup qui peut me aider à comprendre comment se déroulent les travaux. Merci

Modifier: J'ai marqué la première réponse comme correcte mais il ne fonctionne pas, mais je l'ai légèrement modifié et cela a fonctionné.

let tri_seq = 1.0 |> Seq.unfold (fun x -> Some (0.5 * x * (x + 1.0),x + 1.0)) 

Répondre

8

Tout d'abord, pourquoi utilisez-vous match si vous avez un seul cas?

let tri_seq = 1.0 |> Seq.unfold (fun x -> Some (x, 0.5 * x * (x + 1.0))) 

Deuxièmement, qu'est-ce qui ne semble pas fonctionner? Savez-vous que vous produisez une liste infinie?

/Edit: Pour être complet bien, voici la bonne solution, que l'OP se trouvait et affiché comme commentaire:

let tri_seq = 
    1.0 |> Seq.unfold (fun x -> Some (0.5 * x * (x + 1.0), x + 1.0)) 
+0

J'ai essayé , mais la séquence renvoie juste une .. > tri_seq ;; val it: seq = seq [1,0; 1,0; 1,0; 1,0; ...] – masfenix

+0

let tri_seq = 1.0 |> Seq.unfold (fun x -> Some (0.5 * x * (x + 1.0), x + 1.0)) est ce dont j'avais besoin. Merci beaucoup. – masfenix

2

Voici une alternative:

let tri = seq { 
    let n = ref 1.0 
    let diff = ref 2.0 
    while true do 
     yield !n 
     n := !n + !diff 
     diff := !diff + 1.0 
    } 

printfn "%A" (tri |> Seq.take 10 |> Seq.to_list) 
4

Une autre alternative à le code que Brian a posté est d'utiliser la récursivité à la place de la boucle impérative 'while':

let tri = 
    let rec loop(n, diff) = seq { 
    yield n   
    yield! loop(n + diff, diff + 1.0) } 
    loop(1.0, 2.0) 
printfn "%A" (tri |> Seq.take 10 |> Seq.to_list) 

C'est beaucoup moins efficace (il faut donc être un peu prudent ici ...), mais c'est une solution fonctionnelle plus idiomatique, donc il peut être plus facile de voir ce que fait le code.

+0

Merci, mais je n'ai aucune idée de ce que fait le "Seq {}", pas du mot-clé "yield", et ne parle pas du "!". Si vous pouvez prendre le temps d'expliquer, ce serait apprécié! – masfenix

+0

Pas un expert, mais Seq {} signifie que j'en fais une séquence. le rendement est le même que C# - signifie renvoyer la valeur et attendre que le code appelant demande le suivant. rendement! est (je crois) comme Seq.concat - aplatit le seq renvoyé de l'appel récursif et fait un rendement sur chaque élément. – Benjol

+0

un peu d'effort peut être fait pour avoir au moins 'boucle' être récursif de queue, sinon cela ne va pas évoluer – pqnet

1

Je sais que c'est un très vieux, mais je ne comprends pas pourquoi utiliser float quand vous êtes sûr que x * (x + 1) est un nombre pair et en effet divisible par 2. Donc, je voudrais simplement utiliser cette une place (je sais pas beaucoup de différence, mais au moins vous avez une seq int):

let tri_seq = 1 |> Seq.unfold (fun x -> Some (x * (x + 1)/2 , x + 1)) 

tri_seq |> Seq.take 6 |> Seq.toList //[1; 3; 6; 10; 15; 21] 

fiddle

(Sauf si vous face à un nombre bien sûr ....)