用于另一个签名的签名中的类型

时间:2012-01-29 18:01:13

标签: types module ocaml signature

此问题的更清晰版本已发布here

我已经定义了一个签名和两个模块,如下所示。定义2个模块的原因是我可以根据上下文使用MatrixArrayMatrixList ...

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

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

module MatrixList =
  (struct
    type 'a t = 'a list list
    ...
  end: MATRIX)

然后我定义了另一个签名和另外2个与MATRIXMatrixArrayMatrixList相关的模块:

module type PM =
  sig
    type 'a t
    (* val of_matrix: 'a MatrixArray.t -> 'a t *)
    val of_matrix: 'a MATRIX.t -> 'a t
    ...
  end

module PmArray =
  (struct
    type 'a t = 'a array array
    let of_matrix (m: 'a MatrixArray.t) : 'a t =
    ...
  end: PM)

module PmList =
  (struct
    type 'a t = 'a list list
    let of_matrix (m: 'a MatrixList.t) : 'a t =
    ...
  end: PM)

在签名PM中,我可以定义val of_matrix: 'a MatrixArray.t -> 'a t,但我无法定义val of_matrix: 'a MATRIX.t -> 'a tError: Unbound module MATRIX)。所以我猜MATRIX.t总是非法......

我真正想要实现的是......在签名级别of_matrix: 'a MATRIX.t -> 'a PM.t上,但在模块PmArrayof_matrix: 'a MatrixArray.t -> 'a PmArray.t的级别上;在模块级PmListof_matrix: 'a MatrixList.t -> 'a PmList.t

我不知道是否必须定义额外的模块或仿函数来实现这种结构......希望我的关注得到很好的描述,有人可以帮忙吗?

EDIT1:

我只是意识到of_matrix的名称可能会产生误导,例如,它会被称为f。它只代表'a MatrixArray.t -> 'a PmArray.t'a MatrixList.t -> 'a PmList.t类型的函数,其实现内部可能很复杂。而且我想提出类型'a MATRIX.t -> 'a PM.t,遗憾的是不允许这样做。

EDIT2:

我会调用PM作为实例TRIANGLE,并调用PmArray TriagleArray(表示由数组数组表示的三角形),并调用PmList TriangleList(表示由列表列表表示的三角形)。给定矩阵m,函数f (m: a MatrixArray.t) : 'a TriangleArray.t使其左上半部分由对角线分开。

在目前阶段,像: 'a MatrixArray.t -> 'a TriangleList.t这样的函数并不是必需的,虽然以后没有理由将它们排除在外......我在模块级别真正需要的是: a MatrixArray.t -> 'a TriangleArray.t和{{1我希望对它们有一个共同的签名/约束:: a MatrixList.t -> 'a TriangleList.t某处。

1 个答案:

答案 0 :(得分:1)

主要问题似乎是'a MATRIX.t不是一个类型,所以它不能用于构建新的函数类型。这意味着声明val 'a MATRIX.t -> 'a t不是有效的函数定义。

类型签名仅定义类型约束。在大多数情况下,您不需要类型签名,因为它们很容易被模块本身所感染。使用类型签名的主要原因是您计划稍后对代码进行编译。在这种情况下,您需要定义要用作输入和输出到仿函数的类型签名。所有符合该签名的模块都将被允许,无论它们是否实际上属于上述类型。 OCaml在模块和对象层面上确实使用了Duck Typing

因此,简单的解决方案是完全摆脱模块签名PM。这也将减少没有真正语义的代码量。如果你真的需要模块签名(或者当前正在玩模块)。

以下是您问题的一种可能解决方案:

module type MATRIX =
  sig
    type 'a t
  end

module MatrixArray =
  (struct
    type 'a t = 'a array array
    type 'a b = 'a
  end: MATRIX)

module MatrixList =
  (struct
    type 'a t = 'a list list
  end: MATRIX)

  module type PM =
  sig
    type 'a t

  end

module Pm  = functor ( M: MATRIX) ->
  (struct
    type 'a t = 'a M.t
  end: PM with type 'a t = 'a M.t ) 

module PmArray = Pm(MatrixArray)
module PmList = Pm(MatrixList)

并不是说with子句在参数类型'a MATRIX.t之间引入了一个类型等价(实际上不是一个类型,但是一旦实例化了仿函数就变为一个),结果类型'a PM.t(同样不是真的一种)。因此,在实例化仿函数时,必要的等式将保持不变,并且不需要of_matrix函数。

然而,可能有其他解决方案更适合您的需求,例如只删除签名并仅使用模块。