我已经定义了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
得到识别?
答案 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
在浮点数组上是单态的。