在这种情况下我需要函子吗?

发布于 2024-12-07 17:38:25 字数 889 浏览 0 评论 0原文

我在以下代码中使用 Bitstring 模块

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

在这种情况下,函子会可以派上用场来推广此功能,如果是这样,我将如何设置它? (如果有其他不需要函子的方法来做到这一点,那也很高兴知道)

I'm using the Bitstring module in the following code:

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 ) ;;

Note that when you have BITSTRING { vv : 32 }
that vv is expected to be an Int32 value. I'd like to generalize this function to work with different widths of bitstrings; ie, I'd like to create a build_data_n function where the bitstring would be constructied with BITSTRING { vv : n } .

However, the problem here is that if n is less than 32 then the succ function used above would just be the succ for type int. If it's greater than 32 it would be Int64.succ Same issue above in the line let v' = Int32.of_int(v) in - for values less than 32 it would simply be: let v' = v in , whereas for values greater than 32 it would be: let v' = Int64.of_int(v) in

Is this a case where a functor would come in handy to generalize this function and if so, how would I set that up? (and if there's some other way to do this that doesn't require functors, that would be nice to know as well)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

幸福丶如此 2024-12-14 17:38:25

有几种可用的方法。一种是使用函子,类似于以下内容:

(* 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

这些方法中的每一种都可以混合搭配。您还可以将值包装在变体类型或对象中以获得类似的结果。

There are a few approaches available. One is to use a functor, similar to the following:

(* 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

Another is to wrap your data type in a record:

(* 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)

And finally, if you are using OCaml 3.12.0 or later, you can use first class modules:

(* 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

Each of these approaches can be mixed and matched. You may also be able to wrap your values in variant types or objects to get a similar result.

你怎么敢 2024-12-14 17:38:25

对于BITSTRING { vv : n },即使用运行时指定的字段长度,vv 的类型不能依赖于n,因为它不是编译时常量不再存在,因此 vv 被强制为 int64

With BITSTRING { vv : n }, i.e. using runtime-specified field length, the type of vv cannot depend on n as it is not the compile-time constant anymore, so vv is forced to int64.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文