Home > Mobile >  Why I get error saying function in argument for a class not defined - error FS0039: The value or con
Why I get error saying function in argument for a class not defined - error FS0039: The value or con

Time:12-07

I have a class called 'car', which can instantiate objects.

type car (fuelEco: float,fuel:int) =
    let mutable fuelEco = fuelEco
    let mutable tank = 0
    member this.addGas (liter: int) = tank <- liter
    member this.gasLeft () = tank
    member this.drive (km: int) =
        if float(km) > (float(tank) * fuelEco) then raise (InsuficientGas "You can't drive this far - you have insuficient amount of gas")
        else tank <- tank - int((float(km) / fuelEco))

I have another class called 'Assert' (with capital letter), which asserts a number of arguments given to the class Assert.

type Assert (str: string, a:'a, b: 'b,f:('a -> 'a -> bool)) =
    static member test = 
        if (f a (int(b))) then 
            printfn "%A : %A" "Pass" str
        else printfn "%A : %A" "Pass" str

I then have to test Assert by the follwing code:

let fe = 18.3
let mini = new car(fe,0)
Assert.test "GasLeft () - Full?" (mini.gasLeft ()) 10.0 (=)
Assert.test "GasLeft () - Empty?" (mini.gasLeft ()) 0 (=)

For the first test, I would expect to get "Fail" : "GasLeft () - Full?" and for the second test, I would expect to get "Pass" : "GasLeft() - Empty?" when given the arguments specified.

However, F# tells me that f is not defined in the arguments. My f when calling Assert.test is (=), which according to F# takes ('a -> 'a -> bool). Note that I cast b to and int, because it can be given as a float type, so to be sure, that I compare two integers, I cast it to an int first.

So I can't see why it says f is not defined?

CodePudding user response:

The issue is with your Assert class. The arguments were going into the class constructor instead of the static member. A static member does not have access to the state of the class and therefore you get an error.

I fixed this by moving the arguments to the test member and also changed them from being tupled arguments (comma separated) to curried arguments (space separated) so that they can be called in the curried style as you were doing.

type Assert =
    static member test (str: string) (a:'a) (b: 'b) (f:('a -> 'a -> bool)) = 
        if (f a (int(b))) then 
            printfn "%A : %A" "Pass" str
        else printfn "%A : %A" "Pass" str

There seems to be some dangerous mixing of floats and ints. I recommend changing all the number types here to be float, which should make the code more simple and correct.

  • Related