[英]F# How to write a function that takes int list or string list
我在F#中亂搞並嘗試編寫一個可以采用int list
或string list
的函數。 我編寫了一個邏輯上通用的函數,因為我只能修改參數的類型,它將與兩種類型的列表一起運行。 但我不能一般地定義兩者。
這是我的函數,沒有類型注釋:
let contains5 xs =
List.map int xs
|> List.contains 5
當我嘗試注釋函數以獲取通用列表時,我收到警告FS0064: the construct causes the code to be less generic than indicated by the type annotations
。 從理論上講,我不需要注釋這是通用的,但無論如何我都試過了。
我可以在兩個單獨的文件中編譯它,一個用
let stringtest = contains5 ["1";"2";"3";"4"]
和另一個
let inttest = contains5 [1;2;3;4;5]
在每個文件中,編譯成功。 或者,我可以將函數定義和其中一個測試發送給解釋器,類型推斷也可以正常進行。 如果我嘗試編譯,或發送到解釋器,函數定義和兩個測試,我收到error FS0001: This expression was expected to have type string, but here has type int
。
我是否誤解了打字應該如何運作? 我有一個函數,其代碼可以處理一個int列表或一個字符串列表。 我可以用其中任何一個成功測試它。 但我不能在一個處理兩者的程序中使用它?
您可以使用inline
來防止將函數固定到特定類型。
在FSI中,交互式REPL:
> open System;;
> let inline contains5 xs = List.map int xs |> List.contains 5;;
val inline contains5 :
xs: ^a list -> bool when ^a : (static member op_Explicit : ^a -> int)
> [1;2;3] |> contains5;;
val it : bool = false
> ["1";"2";"5"] |> contains5;;
val it : bool = true
請注意,contains5的簽名具有通用元素。 還有更多的是內聯函數在這里 。
這已經在上面正確回答了,所以我只是想知道為什么我認為F#似乎使這很難/迫使我們失去類型安全是一件好事。 我個人認為這些在邏輯上是等價的:
let inline contains5 xs = List.map int xs |> List.contains 5
let stringTest = ["5.00"; "five"; "5"; "-5"; "5,"]
let intTest = [1;2;3;4;5]
contains5 stringTest // OUTPUT: System.FormatException: Input string was not in a correct format.
contains5 intTest // OUTPUT: true
內聯時,編譯器將創建該函數的兩個邏輯上不同的版本。 當在list<int>
上執行時,我們得到一個布爾結果。 當在list<string>
上執行時,我們得到一個布爾結果或一個異常。 我喜歡F#推動我承認這一點。
let maybeInt i =
match Int32.TryParse i with
| true,successfullyParsedInteger -> Some successfullyParsedInteger
| _ -> None
let contains5 xs =
match box xs with
| :? list<int> as ixs ->
ixs |> List.contains 5 |> Ok
| :? list<string> as sxs ->
let successList = sxs |> List.map maybeInt |> List.choose id
Ok (successList |> List.contains 5)
| _ ->
Error "Error - this function expects a list<int> or a list<string> but was passed something else."
let stringTest = ["5.00"; "five"; "5"; "-5"; "5,"]
let intTest = [1;2;3;4;5]
let result1 = contains5 stringTest // OUTPUT: Ok true
let result2 = contains5 intTest // OUTPUT: Ok true
強迫我詢問if some of the values in the string list cannot be parsed, should I drop out and fail, or should I just try and look for any match on any successful parse results?
。
我上面的方法太可怕了。 我將操作字符串的函數與對整數進行操作的函數分開。 我認為你的問題是學術問題,而不是一個真實的用例,所以我希望我在這里沒有過多的切線!
免責聲明:我是初學者,不相信我說的任何話。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.