请解释 ppx_variants_conv make_matcher 方法签名

Please explain the ppx_variants_conv make_matcher method signature

我发现自己想要一种方法来围绕我的代码中的一些大型变体类型做一些代码生成,我发现 ppx_variants_conv (https://github.com/janestreet/ppx_variants_conv)

make_matcher 方法听起来可能对我有用,但没有文档,而且我正在努力阅读示例签名:

  val make_matcher :
       a:(('a -> 'a t)         Variant.t -> 'b -> ('c -> 'd)         * 'e)
    -> b:((char -> 'f t)       Variant.t -> 'e -> (char -> 'd)       * 'g)
    -> c:('h t                 Variant.t -> 'g -> (unit -> 'd)       * 'i)
    -> d:((int -> int -> 'j t) Variant.t -> 'i -> (int -> int -> 'd) * 'k)
    -> 'b
    -> ('c t -> 'd) * 'k

a b cd 标记的参数对应于变体的情况,每个签名的第一部分对应于每个情况的构造函数。 .. 在那之后我有点迷路

'b 'c 'd'k 出现在签名的后半部分而不是 'e 'f 'g 'h 'i 'j

make_matcher 函数中,每个带标签的参数都采用具有一般形式 fun v x -> f, y 的两个参数的函数,其中 v 是表示 first-class 的变体相应的构造函数 x 是折叠在所有 matchers-generating 函数上的值。函数 returns 一对,其中第一个成分,函数 f 实际上是匹配器,如果该变体匹配则将调用该匹配器,并且某些值 y 将传递给下一个 matcher-generating 函数。

让我们举一些例子来说明这一点。首先,让我们定义一些简单的匹配器,例如,

type 'a t =
  | A of 'a
  | B of char
  | C
  | D of int * int
[@@deriving variants]

let matcher init = Variants.make_matcher
    ~a:(fun v (x1 : char) ->
        (fun x -> x+1),Char.code x1)
    ~b:(fun v (x2 : int) ->
        (fun c -> Char.code c),float x2)
    ~c:(fun v (x3 : float) ->
        (fun () -> 0), string_of_float x3)
    ~d:(fun v (x4 : string) ->
        (fun x y -> x + y),[x4])
    init

下面是我们如何使用它,

# let f,s = matcher '*';;
val f : int t -> int = <fun>
val s : Base.string list = ["42."]
# f (A 10);;
- : int = 11
# f (B '*');;
- : int = 42
# f C;;
- : int = 0
# f (D (1,2));;
- : int = 3

老实说,我不知道传递给每个 matcher-generating 函数的额外参数的用途1。可能的想法是,根据初始参数,我们可以生成不同的匹配器。但是如果你不需要这个,那么只需将 () 传递给它 and/or 定义你自己的简化匹配器,忽略这些附加信息,例如,

let make_simple_matcher ~a ~b ~c ~d =
  fst @@Variants.make_matcher
    ~a:(fun _ _ -> a,())
    ~b:(fun _ _ -> b,())
    ~c:(fun _ _ -> c,())
    ~d:(fun _ _ -> d,())
    ()

make_simple_matcher 函数具有预期的类型,

a:('a -> 'b) ->
b:(char -> 'b) -> 
c:(unit -> 'b) -> 
d:(int -> int -> 'b) -> 
'a t -> 'b

1) 查看生成此函数的代码的内部结构并没有太大帮助,因为他们使用此参数的通用名称 acc,这不是很有帮助。