简体   繁体   中英

OCaml compiler error “variant type list has no constructor true”

I have been learning OCaml and have been trying to write a function that takes in a list of lists of type int, which are representing a matrix. For example: [[1;2;3]; [4;5;6]; [7;8;9]] [[1;2;3]; [4;5;6]; [7;8;9]] [[1;2;3]; [4;5;6]; [7;8;9]] and in return I want to return a bool value indicating if it is a proper matrix, or not. The way this is decided is if all rows in the matrix have the same amount of elements (like the example shown above)

Thus, I have created the following function:

let rec matrix lst =
  match lst with
  | h::t -> 
    (match h with
    | a ->
      if (List.length a = List.length (matrix t)) then true else false) 

My function type is not what I'm expecting. It should just be

is_matrix : (int list) list -> bool 

or the general equivalent with a'

I'm getting a compile error saying: the variant type list has no constructor true Any idea what's that about?

let rec getlength x =
  match x with
  | [] -> 0
  | a::b -> List.length a + getlength b


let matrix lst =
  match lst with 
  | [] -> true
  | h::t -> if (getlength h = getlength t) then true else false  

Your original code is wrong because of List.length a = List.length (matrix t) normally matrix t is a boolean, so it's not really clear what does List.length true means.

In your second solution the problem is in h::t -> if (getlength h = getlength t) . getlength is of type 'a list list -> int , so you can't call it with type, let say, 'b (type of h ) and then with type 'b list (type of t ).

But in general I think you are moving in right direction. Simple algorithm may looking like this:

  1. Calculate length of the first element of list,

  2. For each remaining element calculate its length and compare it with result of (1), if they are equal continue, else return false .

  3. Return true if there is no more elements.

This algorithm can be implemented in many different way. I strongly recommend you to do it yourself, but I can't resist to post this simple and elegant solution:

let matrix (h::t) =
    let l = List.length h in
    let rec f = function
        | [] -> true
        | h::t -> if List.length h = l then f t
                  else false in
    f t

Once again, be sure that you fully understand this code before using it.

The problem is in the following expression:

List.length matrix t

This tries to apply List.length to two arguments: matrix and t . This function only takes one argument (a list), so this reports a type error.

You need to add the case for [[]] if you want the type system to understand that you're working with lists of lists.

| [[]] -> true

This would then mean you can use List.length on the lists like your originaly wanted.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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