2015-06-03 2 views
1

Я не совсем уверен, как искать этот вопрос.Расширение функциональности массива int в OCaml

Скажем, я использую кучу функций на int array s, например, вычитая два из них покомпонентно (если они имеют одинаковую длину) и так далее. Есть ли идиоматический способ справиться с этим? Как мне поднять операции на int s (или какой-либо другой тип) на операции на int array s (или массивы какого-либо другого типа)? Должен ли я использовать функтор или использовать другой подход?

Редактировать: Я хочу, чтобы иметь возможность поднимать арифметические операции с числовыми типами, такими как int s или float s с единицами на их соответствующих массивах. Должен ли я просто написать функции?

ответ

3

У вас есть эти «Итераторы в двух списках» для списков. Я полагаю, их будет достаточно для того, что вы хотите сделать.

Я думаю, вы могли бы использовать списки вместо этого (или превращать свои массивы в списки и возвращать их обратно, но это звучит излишне дорого) или просто кодировать эти функции самостоятельно.

Вот пример:

let array_map2 f a a' = 
    let n = Array.length a in 
    assert (n = Array.length a'); 
    if n = 0 then [||] 
    else begin 
    let r = Array.make n (f a.(0) a'.(0)) in 
    for i = 0 to n - 1 do 
     r.(i) <- f a.(i) a'.(i) 
    done ; 
    r 
    end 

array_map2 : ('a -> 'b -> 'c) -> 'a array -> 'b array -> 'c array 

Эта функция работает (если он работает) следующим образом:

array_map2 f [| a1 ; a2 ; ... ; an |] [| b1 ; b2 ; ... ; bn |] = [| f a1 b1 ; f a2 b2 ; ... ; f an bn |] 

Затем, благодаря полиморфизму вы можете поднять свои операции:

array_map2 (+) : int array -> int array -> int array 
array_map2 (+.) : float array -> float array -> float array 
+0

Да, я полагался на сам писать эти функции, но мне также нужно поднять арифметические операции для типов, отличных от 'int', поэтому делать это вручную становится утомительным. Есть идеи? – Dimitrios

+0

Полиморфизм - это ключ, не так ли? Вы можете использовать 'array_map2 (+): int array -> int array -> int array' например. –

+0

Функция 'array_map2', данная @Sheeft, работает для всех типов, а не только для ints. –

3

Просто напишите функции. Нет необходимости использовать функторы или что-то еще, просто держите его простым и лаконичным. Считаемость должна быть главным приоритетом.

Если вы хотите, чтобы ваши функции, чтобы быть в модуле массива, вы можете использовать следующий трюк:

module Array = struct 
    include Array 
    let diff xs ys = ys 
end 

И теперь у вас есть модуль Array со всеми существующими функциями, плюс ваш. Конечно, это не изменит реальный модуль Array и будет иметь эффект только в лексической области.

Update

Если ваш алгоритм достаточно универсален, чтобы зависеть только от какой-то конкретной алгебры, то вы можете абстрактный эта алгебру с типом модуля и использовать функторы или модули первого класса параметризовать код с этой алгеброй. Хорошим примером может служить sum function в интерфейсе Container. Он параметризуется модулем первого класса (модуль, упакованный в значение), который должен реализовать алгебру commutative group (что требуется для функции sum). В принципе, использование что-то вроде этого:

List.sum (module Int) ~f:ident [1;2;3;4] 

или

Array.sum (module Int) ~f:ident [| 1;2;3;4|] 

Кроме того, этот код может быть впоследствии легко переписать принять новый modular implicits, которая будет доступна в следующей версии OCaml.

+0

Итак, если бы мне нужны эти функции для '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' ' t int | Float of float', а затем просто делайте анализ случаев в этих функциях? – Dimitrios

+0

Я отвечу в обновлении – ivg

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