Knows Not Much
Knows Not Much

Reputation: 31576

What's wrong with this F# Code

let compareDiagonal p x y =
    System.Math.Abs((int)(x - (fst p))) <> System.Math.Abs((int)(y  - (snd p)));;

let isAllowed p = function
    | [] -> true
    | list -> List.forall (fun (x, y) -> fst p <> x && snd p <> y && (compareDiagonal p x y))  list;;

let rec solve col list =
    let solCount : int = 0
    match col with
    | col when col < 8 ->
        for row in [0 .. 7] do
            solCount = solCount + if isAllowed (row, col) list then solve (col + 1) ((row, col) :: list) else 0
        solCount        
    | _ -> 1;;

let solCount = solve 0 [];;
solCount;;

I am getting the error

 solCount = solCount + if isAllowed (row, col) list then (solve (col + 1) ((row, col) :: list)) else 0
------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

stdin(335,13): warning FS0020: This expression should have type 'unit', but has type 'bool'. If assigning to a property use the syntax 'obj.Prop <- expr'.

Why am I not able to return the number?

Upvotes: 4

Views: 168

Answers (1)

Samuel Neff
Samuel Neff

Reputation: 74949

There are two related problems.

By default in F# variable are immutable. If you want a mutable variable, you have to declare it, like this:

let mutable solCount : int = 0

And then when you assign values to it instead of using = you have to use <- like this:

solCount <- solCount + if isAllowed (row, col) list then solve (col + 1) ((row, col) :: list) else 0

A complete example followed.

HOWEVER, this is not the correct functional way to do something like this. Instead of using a loop to add up values, use a recursive function to return the cumulative value as you go. Using F# the way functional programs are designed to be used will almost always yield better results, although it takes some getting used to.

Your original example with mutable, not the "functional way":

let compareDiagonal p x y =
    System.Math.Abs((int)(x - (fst p))) <> System.Math.Abs((int)(y  - (snd p)));;

let isAllowed p = function
    | [] -> true
    | list -> List.forall (fun (x, y) -> fst p <> x && snd p <> y && (compareDiagonal p x y))  list;;

let rec solve col list =
    let mutable solCount : int = 0
    match col with
    | col when col < 8 ->
        for row in [0 .. 7] do
            solCount <- solCount + if isAllowed (row, col) list then solve (col + 1) ((row, col) :: list) else 0
        solCount        
    | _ -> 1;;

let solCount = solve 0 [];;
solCount;;

Upvotes: 4

Related Questions