ocaml 多态性 - 强制类型符合多态类型

ocaml polymorphism - coercing a type to be complient with a polymorphic type

我正在尝试做一个简单的分层参数多态类型,当我尝试应用它时,会抛出错误的类型错误。

module H : sig

  type 'a value
  type 'a to_value_children = ('a value -> 'a value list option)
  type 'a node

  val hierarchy: 'a value -> 'a to_value_children -> 'a node

end = struct

  type 'a value
  type 'a to_value_children = ('a value -> 'a value list option)
  type 'a node = {
    data: 'a value;
    children: 'a node list option;
  }

  let hierarchy value to_value_children =
    let rec build v =
      match to_value_children v with
      | None -> {data=v; children = None}
      | Some c -> (
        let node_children =
          List.fold_left (fun a c' ->
            (build c')::a
          ) [] c
        in
        {data=v; children = Some node_children}
      )
    in
    build value

end


type data =
  {
    name: string;
    children: data list option;
  }

let data =
  {
    name = "root";
    children = None
  }

let to_value_children = fun value -> value.children

let () =
  H.hierarchy data to_value_children |> ignore

编译H.hierarchy data to_value_children出现以下错误:data: This expression has type data but an expression was expected of type 'a H.value

谁能建议我如何将这两种类型结合在一起?

您对 H 的签名将 H.value 定义为抽象类型。因此,唯一可以是这种类型的 OCaml 值是由 H 中的函数编辑的值 return。但是,H 中没有 return 类型 H.value 的函数。

因此,无法调用 H.hierarchy。本质上你已经定义了一个没有可用接口的模块。

实在不清楚'a value这个类型应该是什么。目前,它唯一可见的效果是确保模块 H 不可用。使用 H 的当前签名,根本无法构建 'a value 类型的任何值。此外,由于 'a value 是模块实现中的抽象类型,因此即使在模块实现内部也是如此。 如果我敢猜测,你要么试图写:

module H = struct
  type 'a to_value_children = 'a -> 'a list option
  type 'a node = {
    data: 'a;
    children: 'a node list option;
  }

  let hierarchy value to_value_children =
    let rec build data =
      let children =
          match to_value_children data with
          | None -> None
          | Some c -> Some (List.map build c) in
      { data; children }
    in
    build value

end

type data =
  {
    name: string;
    children: data list option;
  }

let data =
  {
    name = "root";
    children = None
  }

let to_value_children value =  value.children

let h =
  H.hierarchy data

根本就没有 'a value,而 hierarchy 可以与具有可能的 to_value_children 功能的任何类型一起使用。

或仿函数版本

type 'a to_children = 'a -> 'a list option
module H(Lower: sig type value val to_children: value to_children end) = struct
  type 'a node = {
    data: 'a;
    children: 'a node list option;
  }
  type value = Lower.value node
  let rec hierarchy data  =
      let children =
          match Lower.to_children data with
          | None -> None
          | Some c -> Some (List.map hierarchy c) in
      { data; children }

   let to_children x = x.children

end
...
module Hdata = H(struct
    type value = data
    let to_children v = v.children
end)
let h1 =
  Hdata.hierarchy data
module H2data = H(Hdata)
let h2 = H2data.hierarchy h1

此版本创建了一个仿函数,它从类节点类型创建同构但不兼容的类节点类型。