ocaml - 这是我需要仿函数的情况吗?

标签 ocaml

我正在使用 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/

相关文章:

Ocamlbuild 覆盖默认选项

types - 使用第一类模块时,类型构造函数 "..."将逃脱其范围

functional-programming - 如何为 OCaml `exception stack trace` 打开 `Toplevel` ?

mysql - Lwt和数据库访问

ocaml - Ocaml 如何决定用户定义运算符的优先级?

ocaml - OCaml 中的模式匹配性能

ocaml - `let` 来自 ocaml 中记录的字段双关

ocaml - MetaOCaml 非限定构造函数

syntax - "open!"是什么意思?

functional-programming - 为什么 OCaml 的线程被认为是 `not enough` ?