8
votes

I'm learning f# and I've got a pretty trivial problem that doesn't seem to make sense. I'm working on Project Euler problem 2 and I've got this:

let fib (x : BigInteger) (y : BigInteger) (max : BigInteger) = 
    let added = x + y
    if added > max then y
    else fib y (x + y) max

I've got the error at the recursive fib call:

Value or constructor 'fib' is not defined

And I'm not sure why. Any help?

3
System.Int32.MaxValue >> 4000000, and "even-valued terms" - BLUEPIXY
@BLUEPIXY: Yea, I know it's not a correct or efficient solution to the problem at the moment. It's an iterative attempt. I'm just trying to fully get all of the syntax. - Steven Evers

3 Answers

13
votes

Because fib is recursive function, it has to start with let rec.

7
votes

In F#, if you want to write a recursive function, you have to use the rec keyword:

let rec fib (x : BigInteger) (y : BigInteger) (max : BigInteger) = 
    let added = x + y
    if added > max then y
    else fib y (x + y) max

That's because in F# under normal circumstances, you can only use identifiers declared before the current code, unlike in C#.

3
votes

Talking of Project Euler Problem 2, you may consider instead of recursion going with Seq.unfold, which is very idiomatic and gives you all Fibonacci numbers at once:

let fibs = Seq.unfold (fun (current, next) ->
    Some(current, (next, current + next))) (1,2)

Now fibs represents lazy sequence of Fibonacci numbers :

>fibs;;
val it : seq<int> = seq[1; 2; 3; 5; ...]

And to make it of BigInteger just substitute (1,2) by (1I,2I), although the solution allows you to stay within ordinary integers.