在OCaml中扩展int数组功能

时间:2015-06-03 16:28:38

标签: ocaml idioms

我不确定如何搜索这个问题。

假设我在int array s上使用了一堆函数,例如分组减去其中两个(如果它们具有相同的长度),依此类推。有没有惯用的方法来处理这个问题?我应该如何将int(或其他类型)上的操作提升到int array(或其他类型的数组)上的操作?我应该使用仿函数还是采取其他方法?

编辑:我希望能够将intfloat等数值类型的算术运算提升到相应数组的算术运算。我还应该写这些函数吗?

2 个答案:

答案 0 :(得分:3)

只需编写功能。没有必要使用仿函数或其他任何东西,只需保持简洁和简洁。可读性应该是主要优先事项。

如果您希望函数位于数组模块中,可以使用以下技巧:

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

现在你有一个模块Array,包含所有现有功能,以及你的功能。当然,这不会改变真正的Array模块,只会在词法范围内起作用。

更新

如果你的算法足够通用,只能依赖某些特定的代数,那么你可以用模块类型抽象这个代数,并使用函子或一流模块用这个代数参数化你的代码。一个很好的例子是Container接口中的sum function。它使用第一类模块(打包为值的模块)进行参数化,必须实现commutative group代数(sum函数需要)。基本上,用法是这样的:

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

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

此外,稍后可以轻松地重写此代码,以采用将在下一版OCaml中提供的新modular implicits

答案 1 :(得分: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