2017-09-26 43 views
3

我想有一個F#函數參數的特定類型:F#函數參數類型的註釋不工作

type NewType = string*int 

let testFunction (arg1:NewType) : NewType = 
    ("resultString", 2) 

testFunction ("test", 3) 

我希望函數的類型是:

NewType -> NewType 

但功能類型是:

string*int -> NewType 

我該怎麼辦才能強制arg1參數的類型爲「NewType」?

回答

4

type NewType = string * int是所謂的類型縮寫。它給出了另一種類型的名稱或別名,但在編譯過程中被擦除。沒有封裝,沒有新的參考,基本上沒有新的類型。

它可以作爲文檔,但F#的編譯器將新名稱和別名類型視爲相同。如果您使用NewType的公用函數/方法創建DLL並嘗試從另一個項目調用它,那麼這種情況尤其明顯 - 您將看到混合結果,就像您的情況一樣。

如果你想達到的只是更好的可讀性,這可能不成問題。如果我在代碼中看到let testFunction (arg1:NewType) : NewType = ...,尤其是在GitHub上沒有智能感知工具提示的網絡中,即使「實際」類型實際上是string * int,這仍能讓我很好地瞭解該函數需要和返回的內容。

如果你想更好的類型安全,通常的做法是確定一個單一的情況下識別聯合,您可以與模式匹配這樣的組合:

type NewType = NewType of (string * int) 

let testFunction (NewType arg1): NewType = 
    NewType ("resultString", 2) 

testFunction (NewType ("test", 3)) 

,您可以點擊這裏閱讀,並從其他文章該系列:https://fsharpforfunandprofit.com/posts/type-abbreviations/

+1

但爲什麼返回類型是「NewType」,爲什麼它使用返回類型而不是參數。順便謝謝你的鏈接! – FraK

+1

@FraK,這是一個很好的問題,而我不知道比其他一個滿意的答案:這是編譯器的當前版本如何決定這樣做(來源例如:https://github.com/fsharp/fsharp /問題/ 717)。正如Tomas所說的那樣,原始類型和別名對於編譯器(和其他工具)是可以互換的,並且它不能保證你什麼時候會看到其中一個。 –

+0

感謝您的回答 – FraK

4

NewType的類型聲明是一個類型別名,這意味着NewType是可交換與string * int - 編譯器把他們當作一回事,有時這意味着它將盡管有類型註釋報告一個取代另一個。

如果你想要一個總是需要通過其全名引用的類型,你需要將它定義爲一個明確的新類型 - 在這一點上,最好使用一個記錄(它也會讓你的名字單獨的字段),但是如果你想要的東西簡潔,你可以使用一個單一的情況下,判別聯合代替:

type NewType = NT of (string*int) 

let testFunction (NT arg1) : NewType = 
    NT("resultString", 2) 

testFunction (NT("test", 3)) 
+0

但爲什麼返回類型總是工作,它是「NewType」而不是字符串* int? – FraK

+0

@FraK我認爲它僅僅是在編譯器中的一些實現細節的副作用 - 統一兩類't1'和't2'時,編譯器檢查,如果他們是平等的 - 然後挑選並使用其中的一個作爲鍵入它顯示的名稱。 –

+0

感謝您的回答 – FraK