Ocaml error with if statement

I have a list of lists, for example [[1; 2; 3]; [2]; [3; 4; 5; 6]; [7; eight; 9; 10] I want to place them in Hashtbl, where the key is the length of the list and the value is the list of lists containing all the sublists of this length.

So, for the example above, the hash will look like this

Key Value 1 [[2]] 3 [[1;2;3]] 4 [[3;4;5;6];[7;8;9;10]] 

In addition, I am also trying to track the length of the longest list, and this number is what the function returns

The code that does this is as follows.

 let hashify lst = let hash = Hashtbl.create 123456 in let rec collector curmax lst = match lst with [] -> curmax | h::t -> let len = (List.length h) in (if ((Hashtbl.mem hash len)=true) then ( let v = (Hashtbl.find hash len) in Hashtbl.add hash len v@ [h] ) (* Line 660 *) else ( Hashtbl.add hash len [h])); (collector (max len curmax) t) in collector 0 lst ;; 

Now when I do this, I get the following error for the code above

 File "all_code.ml", line 600, characters 50-72: Error: This expression has type unit but an expression was expected of type 'a list 

Why Ocaml requires a return type of "list" and how to fix it. thanks in advance Puneet

+4
source share
3 answers

You should probably add parentheses to ( v@ [h]) to avoid parsing it like (Hashtbl.add hash len v)@[h]

And you probably shouldn't pass 123456 to Hashtbl.create , but a reasonable prime number like 307 or 2017

+4
source

You are almost there: @ has a lower priority than applied, and, as Vasily said, Hashtbl.add hash len v@ [h] parsed as (Hashtbl.add hash len v)@[h] . Moreover, you use too many parentheses, and if ((Hashtbl.mem hash len)=true) is unnecessary verbose. Thus, a possible good way to write your function:

 let hashify lst = let hash = Hashtbl.create 307 in let rec collector curmax = function | [] -> curmax | h::t -> let len = List.length h in if Hashtbl.mem hash len then let v = Hashtbl.find hash len in Hashtbl.add hash len ( v@ [h]) else Hashtbl.add hash len [h]; collector (max len curmax) t in collector 0 lst 
+4
source

The hardest work on hash tables in OCaml benefits greatly from the update primitive. There are actually two versions that do different things depending on whether a value exists in the table. This is the one you want to use:

 (* Binds a value to the key if none is already present, and then updates it by applying the provided map function and returns the new value. *) let update hashtbl key default func = let value = try Hashtbl.find hashtbl key with Not_found -> default in let value' = func value in Hashtbl.remove hashtbl key ; Hashtbl.add hashtbl key value' ; value' 

With these primitives, it becomes easier to manage the hash table of lists:

 let prepend hashtbl key item = update hashtbl key [] (fun list -> item :: list) 

From there, moving the list and adding everything to the hash table is pretty simple:

 let hashify lst = let hash = Hashtbl.create 607 in List.fold_left (fun acc list -> let l = List.length list in let _ = prepend hash l list in max acc l ) 0 lst 
+4
source

Source: https://habr.com/ru/post/1396774/


All Articles