[英]Can F# force a parameter to be byte[8]?
我需要一个小实用程序函数,从8个字节的数组生成校验和。
现在,这本身是微不足道的,除了我不能在C#中使用byte Checksum(byte[8] input)
作为方法声明 - 我不能指定数组的大小,所以我必须使用byte []这可以是任何大小,然后在方法体中,我需要检查输入是否为null,长度== 8。
我只是想知道F#是否可以做到这一点? 我听说F#有很多选项来限制函数的可接受参数(例如,判别联盟)?
当然,在这个简单的例子中,F#会有点矫枉过正,但我很好奇。
假设您不希望调用者单独传递它们,则byte[]
arg是IMO罚款; 我所做的唯一改变是我也考虑传入一个起始偏移量(因为我经常发现自己从一个byte[]
的开始处起作用byte[]
- 但这取决于你的上下文)。
如果你真的想避免这种丑陋,你可以考虑把它当作一个long
(或者可以说是更好的(因为负面的权利转移)用于比特工作: ulong
)。 你总是知道它的长度恰好是8个字节,它避免了一些启动查找。
您可以通过移位或通过byte*
和ulong*
不安全强制转换来切换这两种格式
我会说去它的正确方法是创建一个type
,它包装一个byte [8]和使用,作为一个参数。
话虽如此,我可以考虑使用活动模式,但看起来有点矫枉过正:
let (|Is8|NotIs8|) (input : byte[]) = if input.Length = 8 then Is8 else NotIs8
let testFunction (a : 'T[]) =
match a with
| Is8 -> printfn "yes it is 8 in size"
| NotIs8 -> printfn "it is not 8 in size"
这两种语言都不能指定函数采用特定长度的数组。 这个问题是检查调用者是否实际提供具有该长度的数组是非常困难的。 可以检查何时直接由new byte[8]
创建数组,但所有其他情况都需要一些棘手的技术。
这部分是由Code Contracts完成的, Code Contracts是一个可以安装到Visual Studio中并与C#和F#一起使用的附加检查工具。 它允许你写一些像:
byte CheckSum(byte[] data) {
Contract.Requires(data != null);
Contract.Requires(data.Length == 8);
// Implementation
}
代码契约附带了一个工具,当您使用错误大小的数组调用CheckSum
时,该工具会在编译时向您发出警告。 它还可以生成运行时检查(当它无法静态确定调用是否正确时)。
在F#(或任何其他.NET语言)中,类型不能依赖于某个值,因此答案是否定的,您不能这样做。 (请注意,您可以在C ++模板中对其进行编码,因为模板可以依赖于整数参数。)对于byte []使用包装器类型只是将运行时长度检查转换为包装器对象的构造,并没有真正改善情况。
在编译时实际强制正确类型的唯一方法我可以想到使用8元组(或具有8字节字段的等效类型)。 然而,这似乎是一个相当丑陋的解决方案,因为它最终要求您明确地拼出每个单独的字节。 幸运的是已经有满足所述长度约束原始类型: ulong
作为马克建议。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.