Generating Fibonacci series in F#
Other posts tell you how to write the while loop using recursive functions. This is another way by using the Seq library in F#:
// generate an infinite Fibonacci sequence
let fibSeq = Seq.unfold (fun (a,b) -> Some( a+b, (b, a+b) ) ) (0,1)
// take the first few numbers in the sequence and convert the sequence to a list
let fibList = fibSeq |> Seq.takeWhile (fun x -> x<=400 ) |> Seq.toList
for explanation, please ref solution 2 in F# for Project Euler Problems, where the first 50 Euler problems are solved. I think you will be interested in these solutions.
First of all, you're using let
as if it was a statement to mutate a variable, but that's not the case. In F#, let
is used to declare a new value (which may hide any previous values of the same name). If you want to write code using mutation, then you need to use something like:
let c = a + b // declare new local value
l.Add(c)
a <- b // mutate value marked as 'mutable'
b <- c // .. mutate the second value
The second issue with your code is that you're trying to mutate F# list by adding elements to it - F# lists are immutable, so once you create them, you cannot modify them (in particular, there is no Add
member!). If you wanted to write this using mutation, you could write:
let fabList =
// Create a mutable list, so that we can add elements
// (this corresponds to standard .NET 'List<T>' type)
let l = new ResizeArray<_>([1;2])
let mutable a = 1
let mutable b = 2
while l.[l.Count - 1] < 400 do
let c = a + b
l.Add(c) // Add element to the mutable list
a <- b
b <- c
l |> List.ofSeq // Convert any collection type to standard F# list
But, as others already noted, writing the code in this way isn't the idiomatic F# solution. In F#, you would use immutable lists and recursion instead of loops (such as while
). For example like this:
// Recursive function that implements the looping
// (it takes previous two elements, a and b)
let rec fibsRec a b =
if a + b < 400 then
// The current element
let current = a + b
// Calculate all remaining elements recursively
// using 'b' as 'a' and 'current' as 'b' (in the next iteration)
let rest = fibsRec b current
// Return the remaining elements with 'current' appended to the
// front of the resulting list (this constructs new list,
// so there is no mutation here!)
current :: rest
else
[] // generated all elements - return empty list once we're done
// generate list with 1, 2 and all other larger fibonaccis
let fibs = 1::2::(fibsRec 1 2)