与多态变体结合

use*_*221 2 ocaml

我在一个模块中定义了一个变体,另一个模块基本上扩展了变体,但是我使用的是一个多态变体.

为了防止子表达式Extended.exp成为那些Core.exp,结后来被束缚.

module Core = struct
  type 'a expr_f = [
    | `Int of int
    | `Plus of 'a expr_f * 'a expr_f
  ]

  type expr = expr expr_f
end

module Ex = struct
  type 'a expr_f = [
    | 'a Core.expr_f
    | `Times of 'a expr_f * 'a expr_f
  ]

  type expr = expr expr_f
end
Run Code Online (Sandbox Code Playgroud)

这似乎有效,直到我们使用递归函数遍历类型的值Ex.expr.

let rec test : Ex.expr -> Ex.expr = function
  | `Int i -> `Int i
  | `Plus (a, b) -> `Plus (test a, test b)
  | `Times (a, b) -> `Times (test a, test b)
Run Code Online (Sandbox Code Playgroud)

我得到一个类型错误,因为类型Expr.expr_f是:

type 'a expr_f = [
  | `Int of int
  | `Plus of 'a Core.expr_f * 'a Core.expr_f
  | `Times of 'a expr_f * 'a expr_f
]
Run Code Online (Sandbox Code Playgroud)

子表达式正在使用Core.expr_f,不支持其他Times情况.

我该怎么做才能解决这个问题?

我不确定我是否应该不宣布变体并让它保持开放,因为我确实希望从穷举检查中受益.

Dru*_*rup 5

如果你真的想"以后打结",这就是你应该拥有的定义:

module Core = struct
  type 'a expr_f = [
    | `Int of int
    | `Plus of 'a * 'a
  ]

  type expr = expr expr_f
end

module Ex = struct
  type 'a expr_f = [
    | 'a Core.expr_f
    | `Times of 'a * 'a
  ]

  type expr = expr expr_f
end
Run Code Online (Sandbox Code Playgroud)