Reputation: 108
I mainly work in C# and am new to F#/function languages and I'm having a problem with a pretty simple program.
I have a function that creates a record with two integer fields. The fields are chosen System.Random.NextDouble
inside a match
to align with certain probabilities. I then have a for loop that should run the createCustomer
function four times.
The problem I'm having is that the Customer
is the same for all 10 iterations of the for loop and the printfn
inside of getIATime
only seems to execute once.
Program.fs
open Simulation
[<EntryPoint>]
let main argv =
printfn "%A" argv
printfn "Test"
for i in 1 .. 10 do
let mutable customer = createCustomer
printfn "i: %d\tIA: %d\tService: %d" i customer.interArrivalTime customer.serviceTime
ignore (System.Console.ReadLine()) //Wait for keypress @ the end
0 // return an integer exit code
Simulation.fs
module Simulation
type Customer = {
interArrivalTime: int
serviceTime: int
}
let createCustomer =
let getRand =
let random = new System.Random()
fun () -> random.NextDouble()
let getIATime rand =
printf "Random was: %f\n" rand
match rand with
| rand when rand <= 0.09 -> 0
| rand when rand <= 0.26 -> 1
| rand when rand <= 0.53 -> 2
| rand when rand <= 0.73 -> 3
| rand when rand <= 0.88 -> 4
| rand when rand <= 1.0 -> 5
let getServiceTime rand =
match rand with
| rand when rand <= 0.2 -> 1
| rand when rand <= 0.6 -> 2
| rand when rand <= 0.88 -> 3
| rand when rand <= 1.0 -> 4
{interArrivalTime = getIATime (getRand()); serviceTime = getServiceTime (getRand())}
Upvotes: 1
Views: 649
Reputation: 80744
Your getCustomer
is not a function, but a value. Its body is executed only once during program initialization, and the result is stored in a field, which can then be accessed. When you think that you "call" the function, you actually merely reference the value. No calling is going on, because there is nothing to call.
To make getCustomer
a function, give it a parameter. This is how functions differ from values in F#: if you have a parameter, you're a function; if not - you're a value. Since there is no actual data that you'd want to pass to the function, you can give it a "dummy" ("placeholder") parameter of type unit
. This type has exactly one value, and that value is written as ()
:
let createCustomer () =
let getRand =
let random = new System.Random()
fun () -> random.NextDouble()
...
Then call it like this:
for i in 1 .. 10 do
let mutable customer = createCustomer()
printfn "i: %d\tIA: %d\tService: %d" i customer.interArrivalTime customer.serviceTime
Upvotes: 4