我正在使用 Bitstring module在以下代码中:
let build_data_32 v wid =
let num = wid / 32 in
let v' = Int32.of_int(v) in
let rec aux lst vv w = match w with
0 -> lst
| _ -> (BITSTRING { vv : 32 } ) :: ( aux lst (Int32.succ vv) (w-1)) in
Bitstring.concat ( aux [] v' num ) ;;
请注意,当您有 BITSTRING { vv : 32 }
vv 应该是一个 Int32 值。我想概括这个函数来处理不同宽度的位串;即,我想创建一个 build_data_n 函数,其中将使用 BITSTRING { vv : n }
构造位串。
但是,这里的问题是,如果 n 小于 32,那么上面使用的 succ 函数将只是 int 类型的 succ。如果它大于 32,它将是 Int64.succ 上面 let v' = Int32.of_int(v) in
行中的相同问题 - 对于小于 32 的值,它只是:let v' = v in
,而对于大于 32 的值,它将是:let v' = Int64.of_int(v) in
在这种情况下,仿函数是否可以派上用场来泛化此函数?如果可以,我将如何设置它? (如果有其他不需要仿函数的方法来做到这一点,那也很高兴知道)
最佳答案
有几种方法可用。一种是使用仿函数,类似于以下内容:
(* The signature a module needs to match for use below *)
module type S = sig
type t
val succ : t -> t
val of_int : int -> t
end
(* The functor *)
module Make(M : S) = struct
(* You could "open M" here if you wanted to save some typing *)
let build_data v =
M.succ (M.of_int v)
end
(* Making modules with the functor *)
module Implementation32 = Make(Int32)
module Implementation64 = Make(Int64)
let foo32 = Implementation32.build_data 12
let foo64 = Implementation64.build_data 12
另一种是将您的数据类型包装在一条记录中:
(* A record to hold the relevant functions *)
type 'a wrapper_t = { x : 'a; succ : 'a -> 'a }
(* Use values of type 'a wrapper_t in *)
let build_data v =
v.succ v.x
(* Helper function to create 'a wrapper_t values *)
let make_int32_wrapper x = { x = Int32.of_int x; succ = Int32.succ }
let make_int64_wrapper x = { x = Int64.of_int x; succ = Int64.succ }
(* Do something with a wrapped int32 *)
let foo32 = build_data (make_int32_wrapper 12)
let foo64 = build_data (make_int64_wrapper 12)
最后,如果您使用的是 OCaml 3.12.0 或更高版本,则可以使用第一类模块:
(* You can use the module type S from the first example here *)
let build_data (type s) m x =
let module M = (val m : S with type t = s) in
M.succ x
let int32_s = (module Int32 : S with type t = Int32.t)
let int64_s = (module Int64 : S with type t = Int64.t)
let foo32 = build_data int32_s 12l
let foo64 = build_data int64_s 12L
这些方法中的每一种都可以混合和匹配。您也可以将您的值包装在变体类型或对象中以获得类似的结果。
关于ocaml - 这是我需要仿函数的情况吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7640152/