Seq.unfold объяснение в F # - PullRequest
       26

Seq.unfold объяснение в F #

4 голосов
/ 10 февраля 2009

Я пытаюсь лениво создать последовательность, используя F #.

Последовательность определяется следующим образом:

n-й член последовательности числа треугольников задаются как, tn = ½n (п + 1); поэтому первые десять треугольника номера:

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

Вот что у меня есть, но, похоже, это не сработает:

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

Большое спасибо, кто может помочь мне понять, как работает разворачивание. Спасибо

Редактировать: Я пометил первый ответ как правильный, но он не работает, однако я немного изменил его, и он работал.

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

Ответы [ 4 ]

8 голосов
/ 10 февраля 2009

Прежде всего, почему вы используете match, если у вас есть только один случай?

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

Во-вторых, что «не похоже на работу»? Знаете ли вы, что вы создаете бесконечный список?

/ Edit: для полноты картины, вот правильное решение, которое ОП нашел и написал в комментарии:

let tri_seq = 
    1.0 |> Seq.unfold (fun x -> Some (0.5 * x * (x + 1.0), x + 1.0))
4 голосов
/ 11 февраля 2009

Другая альтернатива коду, который опубликовал Брайан, - это использовать рекурсию вместо обязательного цикла 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)

Он гораздо менее эффективен (поэтому вы должны быть здесь немного осторожнее ...), но это более идиоматическое функциональное решение, поэтому может быть легче увидеть, что делает код.

2 голосов
/ 10 февраля 2009

Вот альтернатива:

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)
1 голос
/ 08 мая 2016

Я знаю, что это довольно старое, но я не могу понять, почему использовать float, когда вы уверены, что x * (x + 1) - четное число и действительно делится на 2. Так что я бы просто использовал этот (не большая разница, я знаю, но, по крайней мере, у вас есть int seq):

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]

скрипка

(Если, конечно, вы не имеете дело с огромными числами ...)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...