Design patterns 如何在OCAML中匹配抽象数据类型的构造函数
1) 我有这个模块类型Design patterns 如何在OCAML中匹配抽象数据类型的构造函数,design-patterns,match,ocaml,abstract-data-type,Design Patterns,Match,Ocaml,Abstract Data Type,1) 我有这个模块类型 module type MOD_SIG = sig type t val min val max;; 2) 我根据上面的签名创建了两个模块 module MOD_UINT8 = struct type t = int32 let min = Int32.of_int 0 let max = Int32.of_int 255 end;; module MOD_UINT32 = struct type t = int64 let min =
module type MOD_SIG = sig type t val min val max;;
2) 我根据上面的签名创建了两个模块
module MOD_UINT8 = struct
type t = int32
let min = Int32.of_int 0
let max = Int32.of_int 255 end;;
module MOD_UINT32 = struct
type t = int64
let min = Int64.zero
let max = Int64.of_int 4294967295 end ;;
3) 我创建了2个一流的模块
let uint_8 = (module MOD_UINT8:MOD_SIG);;
let uint_32 = (module MOD_UINT32:MOD_SIG);;
4) 我想编写一个函数,该函数接受一级模块作为参数,并尝试匹配该模块中的特定值是Int32
还是Int64
比如
let module M=(val m:MOD_SIG) in match M.t with
| Int32 -> "Int32"
| Int64 -> "Int64"
我从@octachron那里了解到这是不可能的。虽然我只是想提出这个问题来理解,但是否有解决办法?好吧,也许您可以在模块中添加一个函数,告诉它们的特定值是什么:
type pv = I8 | I32 | I64
module type MOD_SIG = sig
type t
val min
val max
val which_pv : pv
;;
module MOD_UINT8 = struct
type t = int32
let min = Int32.of_int 0
let max = Int32.of_int 255
let which_pv = I8
end;;
module MOD_UINT32 = struct
type t = int64
let min = Int64.zero
let max = Int64.of_int 4294967295
let which_pv = I64
end;;
实际上,有时函数取决于
t
的确切类型,而这正是函数出现的地方。比方说,你想实现一个关于数字的模块,这些数字可以是整数、无符号整数、浮点数。。。在这种情况下,基本运算取决于确切的类型,这里最好使用函子:
module type NSig = sig
type t
val zero : t
val one : t
val min : t
val max : t
val add : t -> t -> t
val mult : t -> t -> t
end;;
module MNumb (N : NSig) = struct
type t = N.t
let min = N.min
let max = N.max
let add = N.add
let mult = N.mult
let rec pow t n =
if n = 0 then N.one
else if n = 1 then t
else let tt = pow t (n / 2) in
if n mod 2 = 0 then tt else mult t tt
end;;
如您所见,要创建
pow
我需要知道1
是如何表示的以及mult
也是如何表示的,但是由于pow
不是一个基本函数,所以我在函子中创建它。因此,您只需将基本类型(int8、int32、int64、float、分数…)提供给函子,然后将其提供给函子以创建更高级的函数。您不能这样做。将代码打包到模块中并生成抽象类型的确切原因是,外部代码不能依赖于精确的实现。您可以对依赖于实现的行为进行抽象,如下所示:
module type MOD_SIG = sig
type t
val min : t
val max : t
val name : string
end
let module M = (val m:MOD_SIG) in
M.name
请使用标记工具突出显示代码块,好吗?照目前的情况,你的问题完全不可读。如果他们正确回答了你的问题,不要忘记接受答案,这会让人们知道这个问题已经解决。明白了。一般来说,你们认为第一类模更好地完成这个或函子?实际上,这取决于你们想做什么。如果你的函数是特定于你选择的类型的,我认为函子更好地实现这一点。让我更新我的答案,让您了解我所看到的更好的解决方案。因此,基本上建议是让Uint8、Uint16、Uint32和Uint64包含类型t val zero:t val one:t val min:t val max:t val add:t->t->t val mult:t->t->t,并且只使用函子向上述模块添加高级函数。然而,我想要的只是在每个模块中都有刚刚超过的值和函数,而不是像pow这样的高级函数。因此,从这个角度来看,我可以假设函子是多余的,我应该简单地使用它们自己的签名和结构创建Uint8、Uint16、Uint32、Uint64,而不是利用函子吗?是的,如果你想知道你使用的是什么类型,我想你可以试试我的第一个解决方案。