2011-12-27 2 views
3

Мне нужно определить матрицу int как тип. Столбец или строка матрицы представляют city, элемент в матрице представляет distance между городом строки и городом столбца. Размерность матрицы может измениться (мы можем добавить или удалить города), но она всегда довольно мала.Определить матрицу int с массивом, списком или картой в OCaml?

стесняется среди int array array, int list list и типа с map, которая определяется следующим образом:

module MatOrd = struct 
    type t = string * string 
    let compare ((a, b): string * string) ((c, d) : string * string) = 
    if Pervasives.compare a c <> 0 
    then Pervasives.compare a c 
    else Pervasives.compare b d 
end 

module MatMap = Map.Make(MatOrd) 

Тогда int MatMap.t может представлять собой матрицу Int. Преимущество этого определения заключается в том, что я могу написать название города как координату матрицы. Wherease for int array array и int list list, кажется, что я должен запомнить наизусть координаты наизусть ...

Кроме того, правда ли, что мы не можем сопоставлять шаблоны с массивом? Например, мы не можем написать:

match a_array with 
    [| first_element; the_rest_elements |] -> ... 

С преимуществами и недостатками, которые я упоминал или нет, какой тип вы предлагаете?

+0

Вы не можете написать 'match a_array с [| first_element; the_rest_elements |] -> ... ', потому что это не так, как вы обращаетесь к элементам массива. 'the_rest_elements' не существует в памяти и не имеет типа в системе типов. Но вы вполне можете справиться с сопоставлением шаблонов с массивами. –

ответ

3

Применимость того или иного типа действительно зависит от того, какие операции вы намерены реализовать с ним. Что вы будете вычислять с помощью своего типа?

Например, вы можете захотеть воспользоваться реализованными там матричными операциями, такими как min-plus multiplication, что может помочь вам с кратчайшим пути. В этом случае имеет смысл использовать матрицы и иметь отдельную функцию string -> int, которая переводит от имени города к матричным координатам. С другой стороны, если вы просто хотите, чтобы хранилище данных, на котором вычислений будет мало, может иметь смысл тип Map, такой как тот, что указан выше.

Это трудно дать очень проницательные ответы, не зная, что вы хотите, чтобы вычислить, но и для ваших предложений:

  • запомнить списки неизменны, следовательно, int list list имеет ограниченную полезность
  • если вы сделаете два мерные массивы, остерегайтесь массивы изменяемые ссылки и аффектации обрабатывают соответствующим образом, так что после следующего:

    let a = Array.make 3 0;; 
    let a = b;; 
    b.(0) <- 42;; 
    

    a.(0) равно 42.

    Язык имеет страстное стратегию оценки, с тем, что еще один нюанс в том, что вы не должны создать массив следующим образом:

    let m = Array.make 2 (Array.make 3 0);; 
    m : int array array = [|[|0; 0; 0|]; [|0; 0; 0|]|] 
    m.(0).(0) <- 1;; 
    - : unit =() 
    m;; 
    - : int array array = [|[|1; 0; 0|]; [|1; 0; 0|]|] 
    

    Внутренний make вызов получает оцененную первым, и та же ссылка разделяемое три линии вашего внешнего массива. См. the FAQ о том, как создавать матрицы.

И, кстати, вы можете сделать шаблон-сопрягая на массивах (relevant manual section показывает картину в нижней части страницы), но вы должны уважать размер вашего массива при размещении переменных шаблонов.К счастью, вы можете использовать _, и, как вы сказали, размер вашего массива довольно мал.

+0

Хорошие ссылки и разумный ответ, как правило, но я не думаю, что вы имеете в виду «пройденный по имени» в этом втором пункте. Ocaml никогда не использует семантику «пропустить по имени». Вот описание того, что на самом деле семантика «пропустить по имени»: http://www.cs.sfu.ca/~cameron/Teaching/383/PassByName.html Кроме того, это потому, что они не, переданные по имени и вместо этого аргумент внешнему конструктору передается значением (и, следовательно, оценивается только один раз), что неудачное создание массива 2-мерного массива не выполняется. –

+0

Конечно! Исправлено, чтобы устранить любую двусмысленность/ошибку – huitseeker

Смежные вопросы