模块的继承及其类型

时间:2012-01-30 16:42:51

标签: inheritance types module ocaml

我已经定义了2个签名和2个模块,如下所示。一个签名来自另一个;一个模块来自另一个模块。

module type MATRIX =
sig
  type 'a t
  ...
end

module type AMATRIX = 
sig
  include MATRIX
  ...
end

module MatrixArray : MATRIX =
struct
  type 'a t = 'a array array
  ...
end

module AMatrixArray : AMATRIX =
struct
  include MatrixArray
  let init (x: 'a) : 'a t =
    Array.make 2 (Array.make 2 x)
  ...
end

但是当我编译它时,它最终给了我一个错误Error: This expression has type 'a array array but an expression was expected of type 'a t = 'a MatrixArray.t

是否有人知道如何保留此继承并使类型'a t = 'a array array得到识别?

3 个答案:

答案 0 :(得分:5)

在代码中:

module MatrixArray : MATRIX = struct
  type 'a t = 'a array array
 ...
end

您强制MatrixArray隐藏'a t的定义。解决问题的一种方法是删除签名约束:

module MatrixArray = struct
  type 'a t = 'a array array
 ...
end

如果要抽象类型MatrixArray,可以稍后将(MatrixArray : MATRIX)替换为t

答案 1 :(得分:2)

实际上,MatrixArray略高于MATRIX:它是MATRIX,其中类型t的实现已知为数组。所以你可以写:

module MatrixArray : MATRIX with type 'a t = 'a array array =
struct
  type 'a t = 'a array array
  ...
end

这样,您可以保留MATRIX约束并检测类型错误,并保留有关类型实际的信息 - 当然,假设您关心的是将类型设为public而不是abstract。

答案 2 :(得分:2)

小心放置过多的抽象:隐藏类型(即使用抽象类型)很好,但OCaml编译器使用清单类型来执行一些优化。抽象类型将阻止编译器执行它们。

在您的情况下可能很有趣的一个例子是OCaml有两个数组表示:标准数组和浮点数的平面数组。如果编译器知道数组中元素的类型,它可以使用正确的表示直接访问数组。但是如果元素的类型是抽象的,编译器将添加一个测试以在两个表示之间进行选择。

如果使用浮点数矩阵,则应保持类型清单,以便编译器在访问这些数组时生成最有效的代码。

一个例子:

let init_array t x =
  for i = 0 to Array.length t - 1 do
    t.(i) <- x
  done

慢得多(在本机代码中)
let init_float_array t (x : float) =
  for i = 0 to Array.length t - 1 do
    t.(i) <- x
  done

因为init_array是多态的,init_float_array在浮点数组上是单态的。