Greg McGuffey
Greg McGuffey

Reputation: 3316

Why doesn't the following recursive call work?

I had the following code:

let rec nextUnusedInteger (r:Random) rangeMax used =
    let index = r.Next(0, rangeMax)
    match used |> List.tryFind (fun i -> i = index) with
    | None -> index
    | Some i -> nextUnusedInteger r rangeMax used

let rec buildRandomIntegerList (rand:Random) rangeMax reserved count acc =
    match count with
    | 0 -> acc
    | _ -> 
        let randomInteger = nextUnusedInteger rand rangeMax reserved
        let newCount = count - 1
        buildRandomIntegerList rand rangemax randomInteger::reserved newCount randomInteger::acc

I got the following compile error:

Type mismatch. Expecting a     'a     but given a     int -> 'a list -> 'a list
The resulting type would be infinite when unifying ''a' 
and 'int -> 'a list -> 'a list'

This value is not a function and cannot be applied

The problem was the inline Cons. The randomInteger::reserved and randomInteger::acc. If I explicitly make values for those, it works. Here is the revised code that works:

let rec nextUnusedInteger rangeMax used =
    let rand = new Random()
    let index = rand.Next(0, rangeMax)
    match used |> List.tryFind (fun i -> i = index) with
    | None -> index
    | Some i -> nextUnusedInteger rangeMax used

let rec buildRandomIntegerList rangeMax reserved count acc =
    match count with
    | 0 -> acc
    | _ -> 
        let randomInteger = nextUnusedInteger rangeMax reserved
        let newCount = count - 1
        let newReserved = randomInteger::reserved
        let newAcc= randomInteger::acc
        buildRandomIntegerList rangeMax newReserved newCount newAcc

The question is why? I see examples all the time using the inline Cons. Why doesn't the original code work?

Upvotes: 0

Views: 68

Answers (1)

Gus
Gus

Reputation: 26174

You can use the inline cons but if the result is passed as function argument it needs parenthesis:

buildRandomIntegerList rand rangemax (randomInteger::reserved) newCount (randomInteger::acc)

Otherwise the compiler creates a partial applied function and tries to concatenate something to a function, which makes no sense and that's what the error message is telling you.

The same applies to other operators, function application has priority over them.

Upvotes: 3

Related Questions