如何将 [@@deriving show] 应用于我的仿函数的模块参数中的类型?
How to apply [@@deriving show] to a type from module parameter of my functor?
我有一个采用 Set
类型的仿函数,例如:
module type MySet = functor (S : Set.S) -> sig
val my_method : S.t -> S.elt -> S.elt list option
end
module MySet_Make : MySet = functor (S : Set.S) -> struct
let my_method set el = Some [el] (* whatever *)
end
module IntSet = Set.Make(Int)
module MyIntSet = MySet_Make(IntSet)
S.elt
是集合的元素类型
我想以某种方式在我的仿函数中将 [@@deriving show]
(从 https://github.com/ocaml-ppx/ppx_deriving#plugin-show)应用到 S.elt
,这样在我的一种方法中我可以依赖 show : S.elt -> string
功能可用。
我觉得这一定是可能的,但我想不出正确的语法。
或者 - 如果有一种方法可以在签名中指定 Set 类型 S
具有“可显示”类型的元素。
例如我可以定义:
module type Showable = sig
type t [@@deriving show]
end
...但我不知道如何将其指定为 (S : Set.S)
元素的类型约束
您可以构造新的签名来指定您需要的确切功能show
:
module MySet_Make(S : sig
include Set.S
val show : elt -> string
end) = struct
let my_method _set el =
print_endline (S.show el);
Some [el]
end
然后您可以通过构建具有所需功能的模块来构建实际的模块实例:
module IntSet = struct
include Set.Make(Int)
(* For other types, this function could be created by just using [@@deriving show] *)
let show = string_of_int
end
module MyIntSet = MySet_Make(IntSet)
好的,在黑暗中又摸索了几个小时后,我找到了一个可以满足我所有需求的食谱...
首先我们定义一个“可显示”类型,表示已应用 [@@deriving show]
(来自 https://github.com/ocaml-ppx/ppx_deriving#plugin-show)的模块类型:
module type Showable = sig
type t
val pp : Format.formatter -> t -> unit
val show : t -> string
end
(不知道有没有办法不用手动定义直接从ppx_deriving.show
获取?)
然后我们 re-define 并扩展 Set
和 Set.OrderedType
(即元素)类型以要求元素是“可显示的”:
module type OrderedShowable = sig
include Set.OrderedType
include Showable with type t := t
end
module ShowableSet = struct
include Set
module type S = sig
include Set.S
end
module Make (Ord : OrderedShowable) = struct
include Set.Make(Ord)
end
end
我认为我对问题中的原始代码感到困惑并使用了某种 higher-order 仿函数语法(?)...我根本不知道它是如何工作的,但是在某些时候我意识到我的 MySet_Make
正在返回一个仿函数而不是一个模块。所以我们现在就解决这个问题,只使用一个普通的仿函数。
我们可以解决的另一件事是使 MySet
成为 ShowableSet
的进一步扩展...因此 MySet_Make
将把元素类型作为参数而不是另一种 Set 类型.这也使最终代码更加简单:
module type MySet = sig
include ShowableSet.S
val my_method : t -> elt -> elt list option
val show_el : elt -> string
end
module AdjacencySet_Make (El : OrderedShowable) : AdjacencySet
with type elt = El.t
= struct
include ShowableSet.Make(El)
let my_method set el = Some [el] (* whatever *)
let show_el el = El.show el (* we can use the "showable" elements! *)
end
那么我们只需要 Int
的 OrderedShowable
版本作为元素类型。 Int
已经被订购了,所以我们只需要通过派生“show”来扩展它,然后我们就可以制作一个具体的 MySet
:
module Int' = struct
include Int
type t = int [@@deriving show]
end
module MyIntSet = MySet_Make(Int')
我们可以像这样使用它:
# let myset = MyIntSet.of_list [3; 2; 8];;
# print_endline (MyIntSet.show_el 3);;
"3"
我有一个采用 Set
类型的仿函数,例如:
module type MySet = functor (S : Set.S) -> sig
val my_method : S.t -> S.elt -> S.elt list option
end
module MySet_Make : MySet = functor (S : Set.S) -> struct
let my_method set el = Some [el] (* whatever *)
end
module IntSet = Set.Make(Int)
module MyIntSet = MySet_Make(IntSet)
S.elt
是集合的元素类型
我想以某种方式在我的仿函数中将 [@@deriving show]
(从 https://github.com/ocaml-ppx/ppx_deriving#plugin-show)应用到 S.elt
,这样在我的一种方法中我可以依赖 show : S.elt -> string
功能可用。
我觉得这一定是可能的,但我想不出正确的语法。
或者 - 如果有一种方法可以在签名中指定 Set 类型 S
具有“可显示”类型的元素。
例如我可以定义:
module type Showable = sig
type t [@@deriving show]
end
...但我不知道如何将其指定为 (S : Set.S)
您可以构造新的签名来指定您需要的确切功能show
:
module MySet_Make(S : sig
include Set.S
val show : elt -> string
end) = struct
let my_method _set el =
print_endline (S.show el);
Some [el]
end
然后您可以通过构建具有所需功能的模块来构建实际的模块实例:
module IntSet = struct
include Set.Make(Int)
(* For other types, this function could be created by just using [@@deriving show] *)
let show = string_of_int
end
module MyIntSet = MySet_Make(IntSet)
好的,在黑暗中又摸索了几个小时后,我找到了一个可以满足我所有需求的食谱...
首先我们定义一个“可显示”类型,表示已应用 [@@deriving show]
(来自 https://github.com/ocaml-ppx/ppx_deriving#plugin-show)的模块类型:
module type Showable = sig
type t
val pp : Format.formatter -> t -> unit
val show : t -> string
end
(不知道有没有办法不用手动定义直接从ppx_deriving.show
获取?)
然后我们 re-define 并扩展 Set
和 Set.OrderedType
(即元素)类型以要求元素是“可显示的”:
module type OrderedShowable = sig
include Set.OrderedType
include Showable with type t := t
end
module ShowableSet = struct
include Set
module type S = sig
include Set.S
end
module Make (Ord : OrderedShowable) = struct
include Set.Make(Ord)
end
end
我认为我对问题中的原始代码感到困惑并使用了某种 higher-order 仿函数语法(?)...我根本不知道它是如何工作的,但是在某些时候我意识到我的 MySet_Make
正在返回一个仿函数而不是一个模块。所以我们现在就解决这个问题,只使用一个普通的仿函数。
我们可以解决的另一件事是使 MySet
成为 ShowableSet
的进一步扩展...因此 MySet_Make
将把元素类型作为参数而不是另一种 Set 类型.这也使最终代码更加简单:
module type MySet = sig
include ShowableSet.S
val my_method : t -> elt -> elt list option
val show_el : elt -> string
end
module AdjacencySet_Make (El : OrderedShowable) : AdjacencySet
with type elt = El.t
= struct
include ShowableSet.Make(El)
let my_method set el = Some [el] (* whatever *)
let show_el el = El.show el (* we can use the "showable" elements! *)
end
那么我们只需要 Int
的 OrderedShowable
版本作为元素类型。 Int
已经被订购了,所以我们只需要通过派生“show”来扩展它,然后我们就可以制作一个具体的 MySet
:
module Int' = struct
include Int
type t = int [@@deriving show]
end
module MyIntSet = MySet_Make(Int')
我们可以像这样使用它:
# let myset = MyIntSet.of_list [3; 2; 8];;
# print_endline (MyIntSet.show_el 3);;
"3"