【问题标题】:OCaml polymorphic variants in pattern matching模式匹配中的 OCaml 多态变体
【发布时间】:2017-07-26 23:21:37
【问题描述】:

我正在通过 AST 转换开发一种小型编程语言。也就是从VM开始,慢慢添加对程序员有帮助的层。

由于每一层都知道如何转换它的新类型,我做了这样的事情:

module AST0 = struct

  type t = [
    | `Halt
    | `In
    | `Out
    | `Add of (int * int * int)
    | `Sub of (int * int * int)
  ]

  let lower (ast : t list) = ast
end

module AST1 = struct
  type t = [
    AST0.t

    | `Inc of int
    | `Dec of int 
    | `Cmp of (int * int * int)
  ]

  let lower (ast : t list) =
    let lower_one = function
      | `Inc a -> [`Add (a, a, `Imm 1)]
      | `Dec a -> [`Sub (a, a, `Imm 1)]
      | `Cmp (a, b) -> [`Sub (13, a, b)]
      | (x : AST0.t) -> AST0.lower [x]      (* <--- problem line *)
    in
    List.concat @@ List.map lower_one ast
end

不幸的是我得到了错误:

File "stackoverflow.ml", line 28, characters 8-20:
Error: This pattern matches values of type AST0.t
       but a pattern was expected which matches values of type
         [? `Cmp of 'a * 'b | `Dec of 'c | `Inc of 'd ]
       The first variant type does not allow tag(s) `Cmp, `Dec, `Inc

我认为,由于编译器足够聪明,可以注意到我没有在任意匹配情况下处理 X Y 和 Z 变体,因此它可以判断 AST1.lower 中的 x 实际上永远不会是 CmpIncDec。好像不是这样的。

我是否误解了 OCaml 的类型系统?我错过了一些明显的东西吗?这是一种愚蠢的方法吗?

【问题讨论】:

    标签: pattern-matching ocaml abstract-syntax-tree


    【解决方案1】:

    您不能在本地限制案例模式的类型。类型约束: AST0.t 也将其他模式的类型强制为AST0.t。这就是为什么您的代码不进行类型检查的原因; `Inc 不包含在 AST0.t 中。

    但是,OCaml 中有一个简洁的功能可以完全满足您的需求。 使用#AST0.t 模式别名,而不是类型约束。详情见https://caml.inria.fr/pub/docs/manual-ocaml/lablexamples.html#sec46

      (* I fixed several other trivial typing problems *)
      let lower (ast : t list) =
        let lower_one = function
          | `Inc a -> [`Add (a, a, 1)]
          | `Dec a -> [`Sub (a, a, 1)]
          | `Cmp (a, b, c) -> [`Sub (13, a, b)]
          | #AST0.t as x -> AST0.lower [x]     (* <--- problem line *)
        in
        List.concat @@ List.map lower_one ast
    

    #AST0.t as x不仅是(`Halt | `In | `Out | `And _ | `Sub _ as x)的缩写,还把-&gt;右侧的x的类型从[&gt; AST1.t]改为[&gt; AST0.t]。您可以在那里将其用作AST0.t

    【讨论】:

    • 所以这似乎修复了我的一个图层,但没有修复另一个图层。我现在正在调查...
    • 正如我所料,由于我做了一些愚蠢的事情,另一层被破坏了。感谢您的帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-05
    • 1970-01-01
    • 2022-01-11
    • 2011-05-31
    相关资源
    最近更新 更多