[英]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.