【问题标题】:Need and impossibility of having a type of a signature需要和不可能拥有一种签名
【发布时间】:2012-01-30 00:12:14
【问题描述】:

我已经定义了 2 个签名和 4 个模块如下,它工作正常:

module type TRIANGLE =
  sig
    type 'a t
    val get ...
    val set ...
    ...
  end

module type MATRIX =
  sig
    type 'a t
    val unionArrayArray: 'a TriangleArray.t -> 'a TriangleArray.t -> 'a t
    val unionListList: 'a TriangleList.t -> 'a TriangleList.t -> 'a t
    val unionArrayList: 'a TriangleArray.t -> 'a TriangleList.t -> 'a t
    val unionListArray: 'a TriangleList.t -> 'a TriangleArray.t -> 'a t
    ...
  end

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

and MatrixList: MATRIX =
  struct
    type 'a t = 'a list list
    ...
  end

and TriangleArray: TRIANGLE =
  struct
    type 'a t = 'a array array
    ...
  end

and TriangleList: TRIANGLE =
  struct
    type 'a t = 'a list list
    ...
  end

TRIANGLEMATRIX 是两个并行签名。函数unionXXXX 采用两个直角三角形,如果它们的边长相同,则构建一个矩阵。

模块XXXXArray内部由array of array实现,模块XXXXList内部由list of list实现。但是它们可以具有相同的签名XXXX,其中包括setget...等功能。

这种设计的问题在于,TRIANGLE中的setget等函数,4个unionXXXX函数可以有相同的实现。我们只需要一个函数union,它的类型实际上是: 'a TRIANGLE.t -> 'a TRIANGLE.t -> 'a MATRIX.t

但如果我将签名MATRIX 定义如下,编译器会在union 的签名处停止并给出Error: Unbound module Triangle

module type TRIANGLE =
  sig
    type 'a t
    val get ...
    val set ...
    ...
  end

module type MATRIX =
  sig
    type 'a t
    val union: 'a TRIANGLE.t -> 'a TRIANGLE.t -> 'a t
    ...
  end

我希望我已经展示了将 4 个 unionXXXX 函数合并到一个 union 更好,但是很遗憾我们不能指定它的类型,因为缺少 'a TRIANGLE.t,要么在签名MATRIX 或模块中的MatrixXXXX

我希望我的需求和顾虑已被清楚地描述,有没有人有解决方案或更好的设计?

Edit1 :按照评论的建议更改字母的大小写...

【问题讨论】:

    标签: types module ocaml signature


    【解决方案1】:

    首先,关于约定:通常期望模块名称具有CamelCase 格式,模块类型名称具有ALL_UPPERCASE 格式。我读了两遍才注意到您正在处理模块类型而不是模块。

    所以,你在这里想说的是,任何实现模块类型MATRIX 的模块都应该能够,对于实现TRIANGLE任何 模块Triangle,提供此签名:

    type 'a t
    val union : 'a Triangle.t -> 'a Triangle.t -> 'a t
    

    这样表达全称量词是不可能的。你应该做的是使用存在量词和函子:

    module type MATRIX = sig
      module Triangle : TRIANGLE 
      type 'a t 
      val union : 'a Triangle.t -> 'a Triangle.t -> 'a t
    end
    
    module MatrixOfTriangle = functor (Triangle:TRIANGLE) -> struct
      module Triangle = Triangle
      type 'a t = ...
      let union t1 t2 = ...
    end
    

    这确实会强制您在代码中的任何给定点指定您正在处理的三角形,但您可以使用带有TRIANGLE 参数的函子来避免停留在一种类型的三角形上。

    【讨论】:

    • 感谢您的评论,我猜module type MatrixOfTriangle 应该是module MatrixOfTriangle
    • "但是你可以使用带有 TRIANGLE 参数的函子来避免停留在一种类型的三角形上。" ==> 你这是什么意思?看来我们不能写module M = MatrixOfTriangle(TRIANGLE)
    • 其实我还有其他的功能,比如split: 'a Matrix.t -> 'a Triangle.t * 'a Triangle。这就是我递归定义MatrixXXXXTriangleXXXX 的原因。如果我按照您的方法,最好在TRIANGLE 中添加module Matrix: MATRIX。你知道怎么做吗?我已经发布了这个问题here
    • 需要定义一个实现TRIANGLETriangle模块,写成module M = MatrixOfTriangle(Triangle)。如果你有更多的功能,添加到MATRIX并在MatrixOfTriangle中定义。
    • 按照你的方法,还是报错here,你能看看吗?
    猜你喜欢
    • 1970-01-01
    • 2013-03-18
    • 1970-01-01
    • 1970-01-01
    • 2013-06-12
    • 1970-01-01
    • 2020-03-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多