在 OCaml 中扩展 int 数组功能
Extending int array functionality in OCaml
我不太确定如何搜索这个问题。
假设我在 int array
上使用了一堆函数,例如按分量减去其中的两个(如果它们具有相同的长度)等等。有没有一种惯用的方法来处理这个问题?我应该如何将 int
s(或其他类型)上的操作提升为 int array
s(或其他类型的数组)上的操作?我应该使用仿函数还是采用其他方法?
编辑:我希望能够将 int
s 或 float
s 等数字类型的算术运算提升到相应数组上的算术运算。我还是应该只写函数吗?
写函数就好了。无需使用仿函数或其他任何东西,只需保持简单明了即可。可读性应该是首要任务。
如果你想让你的函数在数组模块中,你可以使用以下技巧:
module Array = struct
include Array
let diff xs ys = ys
end
现在您有了一个模块 Array
,其中包含所有现有功能以及您的功能。当然,这不会改变真正的 Array
模块,只会在词法范围内起作用。
更新
如果您的算法足够通用,仅依赖于某些特定的代数,那么您可以使用模块类型抽象该代数,并使用函子或 first-class 模块通过该代数参数化您的代码。一个很好的例子是 sum
function in Container
interface. It is parametrized with a first class module (a module packed into a value), that must implement commutative group 代数(求和函数所必需的)。基本上,用法是这样的:
List.sum (module Int) ~f:ident [1;2;3;4]
或
Array.sum (module Int) ~f:ident [| 1;2;3;4|]
此外,此代码稍后可以轻松重写以采用新的 modular implicits,它将在下一版本的 OCaml 中可用。
您有这些 'Iterators on two lists' 列表。
我想它们足以满足您的需求。
我想您可以改用列表(或者将您的数组转换为列表并再次将它们转换回来,但这听起来不必要地昂贵),或者简单地自己编写这些函数。
这是一个例子:
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
我不太确定如何搜索这个问题。
假设我在 int array
上使用了一堆函数,例如按分量减去其中的两个(如果它们具有相同的长度)等等。有没有一种惯用的方法来处理这个问题?我应该如何将 int
s(或其他类型)上的操作提升为 int array
s(或其他类型的数组)上的操作?我应该使用仿函数还是采用其他方法?
编辑:我希望能够将 int
s 或 float
s 等数字类型的算术运算提升到相应数组上的算术运算。我还是应该只写函数吗?
写函数就好了。无需使用仿函数或其他任何东西,只需保持简单明了即可。可读性应该是首要任务。
如果你想让你的函数在数组模块中,你可以使用以下技巧:
module Array = struct
include Array
let diff xs ys = ys
end
现在您有了一个模块 Array
,其中包含所有现有功能以及您的功能。当然,这不会改变真正的 Array
模块,只会在词法范围内起作用。
更新
如果您的算法足够通用,仅依赖于某些特定的代数,那么您可以使用模块类型抽象该代数,并使用函子或 first-class 模块通过该代数参数化您的代码。一个很好的例子是 sum
function in Container
interface. It is parametrized with a first class module (a module packed into a value), that must implement commutative group 代数(求和函数所必需的)。基本上,用法是这样的:
List.sum (module Int) ~f:ident [1;2;3;4]
或
Array.sum (module Int) ~f:ident [| 1;2;3;4|]
此外,此代码稍后可以轻松重写以采用新的 modular implicits,它将在下一版本的 OCaml 中可用。
您有这些 'Iterators on two lists' 列表。 我想它们足以满足您的需求。
我想您可以改用列表(或者将您的数组转换为列表并再次将它们转换回来,但这听起来不必要地昂贵),或者简单地自己编写这些函数。
这是一个例子:
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