【问题标题】:Polymorphic variants and variance多态变体和变异
【发布时间】:2014-04-01 10:23:15
【问题描述】:

我正在尝试在 OCaml 中创建一个过程对象语言系统。一般的想法是将多态变量的值存储在一个数组中,并让程序更新这个数组(命令式):

module StrMap = Map.Make(String) 

module IntMap = Map.Make(struct type t = int let compare = compare end)

(* store generic labeled objects *)
type 'a env = ([> ] as 'a) IntMap.t

(* a procedure working on such an object array *)
type 'a procedure = 'a env -> 'a env

(* store procedures *)
type 'a proc_table = ('a procedure) StrMap.t

let do_iinc = function 
  | `Int n -> `Int (n+1)

let iinc x env = 
  let v = do_iinc (IntMap.find x env) in 
  IntMap.add x v env

let do_finc = function 
  | `Float f -> `Float (f +. 1.0)

let finc x env = IntMap.add x (do_finc (IntMap.find x env)) env

(* type error :( *)
let table  = 
  StrMap.add "iinc" (iinc 0)
         (StrMap.add "finc" (finc 1)
                 StrMap.empty)

这让我很困惑。我的“更新”对于具体类型是不变的。 OCaml 不应该能够找出该表:([`Float of float ; `Int of int ] procedure) StrMap.t 吗?

我怀疑问题与 map 的方差有关,但我无法确认,因为我无法使用具体的多态变体注释类型。

我的想法在 OCaml 中是否可行?

【问题讨论】:

    标签: polymorphism ocaml variance


    【解决方案1】:

    这个函数的类型:

    let do_finc = function 
      | `Float f -> `Float (f +. 1.0)
    

    [< `Float of float ] -> [> `Float of float ]。换句话说,它将至多具有`Float替代的任何变体类型作为输入;即,要么有 `Float 替代品,要么根本没有替代品。在我看来,您希望该函数适用于具有至少 `Float 替代的变体,即具有`Float 和任意数量的其他变体的变体:

    let do_finc = function 
      | `Float f -> `Float (f +. 1.0)
      | _ -> failwith "wanted a float"
    

    如果我以这种方式更改do_iincdo_finc,则表格的类型更接近您想要的。

    我完全不确定您的计划是否可行,因为您可能希望 OCaml 接受类型不正确的程序并在运行时抱怨。相反,OCaml 在编译时抱怨,您可能必须编写自己的代码才能在运行时抱怨:-) 但这可能有助于解决第一个问题。

    【讨论】:

      【解决方案2】:

      我不完全清楚你要做什么,但我觉得它不安全。

      您的finc 1 没有您建议的[`Float of float ; `Int of int ] procedure 类型,它的类型为[`Float of float ] procedure,相当于[`Float of float] IntMap.t -> [`Float of float] IntMap.t

      这是因为 do_finc 函数(应用于参数成员 env)只知道如何处理 [`Float of float] - 它不适用于 [`Int of int]

      如果table 具有您想要的类型,请考虑以下表达式中会发生什么:

      let f = StrMap.find "finc" table in
      let m = IntMap.add 1 (`Int 4) IntMap.empty in
        f m
      

      【讨论】:

      • 我希望程序抛出一个“不匹配的表达式”异常,就像任何不完整的模式一样。整个想法是在 OCaml 中构建一个本质上不安全的概念(即类似演员表的东西),因此不安全的操作是不可避免的。
      • 对多态变体的类型检查故意避免允许不详尽的匹配,因为 99.99% 的时间你不想要它们。如果你确实想要,那么你将不得不添加你自己的默认情况,这会引发异常。
      猜你喜欢
      • 2022-01-16
      • 1970-01-01
      • 1970-01-01
      • 2020-06-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-13
      • 1970-01-01
      相关资源
      最近更新 更多