Ошибка Ocaml с оператором if - PullRequest
       0

Ошибка Ocaml с оператором if

4 голосов
/ 16 февраля 2012

У меня есть список списков, например [[1; 2; 3]; [2]; [3; 4; 5; 6]; [7; 8; 9; 10] Я хочу поместить их в Hashtbl, где ключ - это длина списка, а значение - список списков, который содержит все подсписки заданной длины.

Так что для примера выше хеш будет выглядеть следующим образом

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

Кроме того, я также пытаюсь отслеживать длину самого длинного списка, и это число - то, что возвращается функцией

Код, который делает это следующим образом.

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
    ;;

Теперь, когда я делаю это, я получаю следующую ошибку для кода выше

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

Почему Ocaml требует возвращаемый тип 'списка и как мне это исправить. заранее спасибо Puneet

Ответы [ 3 ]

4 голосов
/ 16 февраля 2012

Вы почти там: @ имеет более низкий приоритет, чем применяется, и, как сказал Василий, Hashtbl.add hash len v@[h] анализируется как (Hashtbl.add hash len v)@[h].Кроме того, вы используете слишком много круглых скобок, а if ((Hashtbl.mem hash len)=true) - ненужное многословие.Итак, возможный хороший способ написать вашу функцию:

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 голосов
/ 16 февраля 2012

Большая часть тяжелой работы с хеш-таблицами в OCaml чрезвычайно выигрывает от примитива обновления. На самом деле есть две версии, которые делают разные вещи в зависимости от того, существует ли значение в таблице. Это тот, который вы хотите использовать:

(* 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'

С этими примитивами становится просто управлять хэш-таблицей списков:

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

Оттуда просмотреть список и добавить все в хеш-таблицу довольно просто:

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 голосов
/ 16 февраля 2012

Вы, вероятно, должны добавить круглые скобки в (v@[h]), чтобы избежать их разбора на (Hashtbl.add hash len v)@[h]

И, вероятно, вам не следует передавать 123456 на Hashtbl.create, а разумное простое число, например 307 или 2017

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...