我有一些科学项目.那里有各种长度的矢量/方形矩阵.显然(例如)长度为2的向量不能添加到长度为3的向量中(依此类推).有几个.NET库,它们处理向量/矩阵.所有这些都有通用的载体/矩阵或者有一些非常特殊的载体/矩阵,它们不能满足需要.
大多数(如果不是全部)这些库可以从列表或数组创建向量.不幸的是,如果我错误地给出了一个错误长度的输入数组,那么我将得到一个错误长度的向量,然后一切都会在运行时爆炸!
我想知道是否有可能在编译时检查数组长度,以便得到编译错误,如果,让我们说,我尝试将5元素数组传递给长度为2"构造函数"的向量.毕竟,printfn几乎就是这样!
我想到了F#类型的提供商,但我不确定如何在这里应用它们.
非常感谢!
感谢OP提出了一个有趣的问题.我的答案频率下降并不是因为不愿意提供帮助,而是因为有一些问题引起了我的兴趣.
我们在F#中没有依赖类型,而F#不支持带有数字类型参数的泛型(如C++).
但是,我们可以为不同的维度创建不同的类型Dim1,Dim2依此类推,并将它们作为类型参数提供.
这将允许我们有一个类型签名,apply它应用一个像这样的矩阵的向量:
let apply (m : Matrix<'R, 'C>) (v : Vector<'C>) : Vector<'R> = …
Run Code Online (Sandbox Code Playgroud)
除非矩阵的列与向量的长度匹配,否则代码将无法编译.此外; 结果向量的长度是列的行数.
一种方法是定义一个接口IDimension和一些表示不同维度的具体实现.
type IDimension =
interface
abstract Size : int
end
type Dim1 () = class interface IDimension with member x.Size = 1 end end
type Dim2 () = class interface IDimension with member x.Size = 2 end end
Run Code Online (Sandbox Code Playgroud)
然后可以像这样实现矢量和矩阵
type Vector<'Dim when 'Dim :> IDimension
and 'Dim : (new : unit -> 'Dim)
> () =
class
let dim = new 'Dim()
let vs = Array.zeroCreate<float> dim.Size
member x.Dim = dim
member x.Values = vs
end
type Matrix<'RowDim, 'ColumnDim when 'RowDim :> IDimension
and 'RowDim : (new : unit -> 'RowDim)
and 'ColumnDim :> IDimension
and 'ColumnDim : (new : unit -> 'ColumnDim)
> () =
class
let rowDim = new 'RowDim()
let columnDim = new 'ColumnDim()
let vs = Array.zeroCreate<float> (rowDim.Size*columnDim.Size)
member x.RowDim = rowDim
member x.ColumnDim = columnDim
member x.Values = vs
end
Run Code Online (Sandbox Code Playgroud)
最后,这允许我们编写如下代码:
let m76 = Matrix<Dim7, Dim6> ()
let v6 = Vector<Dim6> ()
let v7 = apply m76 v6 // Vector<Dim7>
// Doesn't compile because v7 has the wrong dimension
let vv = apply m76 v7
Run Code Online (Sandbox Code Playgroud)
如果你需要各种各样的维度(因为你有一个代数递增/递减向量/矩阵的维度),你可以使用一些教会数字的智能变体来支持它.
如果这个可用或不可用完全取决于读者我认为.
PS.
如果它们适用于比浮子更多的类型,也许也可以使用单位措施.