简体   繁体   English

OCaml 此变体表达式应具有单位类型

[英]OCaml This variant expression is expected to have type unit

I'm having a problem with if statements that I cannot figure out.我无法弄清楚 if 语句的问题。
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.我测试了 if 语句在其他方法中返回真/假,它工作得很好。 I don't know why it wouldn't work in this scenario so if anyone can help please do.我不知道为什么它在这种情况下不起作用,所以如果有人可以帮忙,请做。

A more functional solution would be to use Array.iteri :更实用的解决方案是使用Array.iteri

let queen_targeting (chess:chess_board) (x0,y0) =
  let exception Return of bool in
  let threat y x case =
    if case = 'Q' && (x = x0 || y = y0 || x - x0 = y - y0) then
      raise (Return true)
  in
  match Array.iteri (fun y -> Array.iteri (threat y)) chess with
  | () -> false
  | exception Return b -> b

Here the exception is used for returning as soon that we find a queen targeting the position.此处的异常用于在我们找到针对 position 的皇后后立即返回。

A "for expression" must return unit , so the result is not propagated. “for 表达式”必须返回unit ,因此不会传播结果。 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);;

The other answers have addressed your immediate question, but there are some opportunities to address issues in your code that aren't well-suited to a comment.其他答案已经解决了您的直接问题,但是有一些机会可以解决您的代码中不适合发表评论的问题。 Hopefully these suggestions will make it easier to reason about your code in the future by eliminating extraneous noise.希望这些建议可以通过消除多余的噪音,使您将来更容易推理您的代码。

It will sound pedantic, but try to remember that there are no conditional statements in OCaml.这听起来很迂腐,但请记住,OCaml 中没有条件语句 Rather they are expressions which have a value.相反,它们是具有值的表达式 I suspect you understand this already, but terminology is important.我怀疑你已经明白这一点,但术语很重要。

Additionally, there are some issues with how you're using conditionals.此外,您使用条件的方式也存在一些问题。 If the only thing you're doing is returning true or false, then just use the boolean expression directly.如果您要做的唯一事情是返回 true 或 false,那么只需直接使用 boolean 表达式。 Consider a simple example.考虑一个简单的例子。

if a < b && b < c then true else false

This is no different than:这与:

a < b && b < c

Thirdly, when you have nested conditionals, these can often be simplified.第三,当你有嵌套的条件时,这些通常可以被简化。 I'm going to reform your code a little bit and remove the comments for now.我将稍微修改您的代码并暂时删除注释。

if chess.(y).(x) = 'Q' then
  if x = x0 || y = y0 || x - x0 = y - y0 then 
    true
  else 
    false

We know we can simplify this into:我们知道我们可以将其简化为:

if chess.(y).(x) = 'Q' then
  x = x0 || y = y0 || x - x0 = y - y0 

But we'll only check for the ||但我们只会检查|| ed conditions if the first condition checks out, so we can rewrite this whole thing as:如果第一个条件检查,则 ed 条件,因此我们可以将整个事情重写为:

chess.(y).(x) = 'Q' && (x = x0 || y = y0 || x - x0 = y - y0) 

This can be seen (but not elaborated on) in the answer @octachron posted.这可以在@octachron 发布的答案中看到(但未详细说明)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM