if-statementcompiler-errorsocaml

OCaml This variant expression is expected to have type unit


I'm having a problem with if statements that I cannot figure out.
My code:

type chess_board = char array array;;
type position = int * int;;

let chess_board_1:chess_board = [|
    [|' ';' ';' ';' ';' ';' ';' ';' '|];
    [|' ';' ';' ';' ';' ';' ';' ';' '|];
    [|' ';' ';' ';' ';' ';' ';' ';' '|];
    [|' ';' ';' ';' ';' ';' ';' ';' '|];
    [|' ';' ';' ';' ';' ';' ';' ';' '|];
    [|' ';' ';' ';' ';' ';' ';' ';' '|];
    [|' ';' ';' ';' ';' ';' ';'Q';' '|];
    [|' ';' ';' ';' ';' ';' ';' ';' '|];
    |];;
    
let queen_targeting (chess:chess_board) pos =
    match pos with
    |(x0, y0) ->
        for y = 0 to Array.length chess -1 do
            for x = 0 to Array.length chess.(y) -1 do
                if chess.(y).(x) = 'Q' 
                then
                    if (
                        x = x0 ||         (* Check horizontaly *)
                        y = y0 ||         (* Check verticaly *)
                        x - x0 = y - y0   (* Check diagonaly *)
                    ) 
                    then true
                    else false
            done
        done
;;

queen_targeting chess_board_1 (3, 3);; (* Expected true *)

I get this ERROR message:

File "[32]", line 27, characters 25-29:
Error: This variant expression is expected to have type unit
       The constructor true does not belong to type unit
Characters 874-878:
                      then true

I have no clue what this means. I tested if statements returning true/false in other methods and it worked just fine. I don't know why it wouldn't work in this scenario so if anyone can help please do.


Solution

  • A "for expression" must return unit, so the result is not propagated. For example:

    # let x = for y = 0 to 10 do true done;;
    

    leads emit this warning:

    Warning 10: this expression should have type unit.
    val x : unit = ()
    

    A solution would be to use a mutable reference:

    type chess_board = char array array;;
    type position = int * int;;
    
    let chess_board_1:chess_board = [|
        [|' ';' ';' ';' ';' ';' ';' ';' '|];
        [|' ';' ';' ';' ';' ';' ';' ';' '|];
        [|' ';' ';' ';' ';' ';' ';' ';' '|];
        [|' ';' ';' ';' ';' ';' ';' ';' '|];
        [|' ';' ';' ';' ';' ';' ';' ';' '|];
        [|' ';' ';' ';' ';' ';' ';' ';' '|];
        [|' ';' ';' ';' ';' ';' ';'Q';' '|];
        [|' ';' ';' ';' ';' ';' ';' ';' '|];
        |];;
        
    let queen_targeting (chess:chess_board) pos =
        match pos with
        |(x0, y0) ->
            let result = ref false in
            for y = 0 to Array.length chess -1 do
                for x = 0 to Array.length chess.(y) -1 do
                    if chess.(y).(x) = 'Q' 
                    then
                        if (
                            x = x0 ||         (* Check horizontaly *)
                            y = y0 ||         (* Check verticaly *)
                            x - x0 = y - y0   (* Check diagonaly *)
                        ) 
                        then result := true
                        else result := false
                done
            done;
            false || !result
    
    ;;
    
    queen_targeting chess_board_1 (3, 3);;