2010-06-07 48 views
2

我看到Seq有一個從IEnumerable到Seq的強制轉換函數,但我如何才能使它工作?如何避免F#的Seq.cast出現「值限制」錯誤?

open System.Text.RegularExpressions;; 
let v = Regex.Match("abcd", "(ab)");; 
Seq.cast (v.Captures);; 

這產生,

錯誤FS0030:值限制。值'it'已被推斷爲具有通用類型 val it:seq <'_a>
要麼將​​其定義爲簡單的數據項,要麼將其設爲具有顯式參數的函數,要麼將其作爲一個函數,如果您不打算爲通用的,添加一個類型註釋。

回答

8

更明確一些類型:

Seq.cast<Match> (v.Captures) 

否則cast需要上下文來推斷正確的返回類型,像有一個行本身沒有這樣的上下文類型推斷使用。

(這條線轉換非通用IEnumerable爲通用IEnumerable<Match>又名seq<Match>。)

6

其實有指定你想要得到的類型有兩種方式。布賴恩張貼如何通過顯式指定類型參數的函數來做到這一點:

let res = Seq.cast<Match> v.Captures 

另一種選擇是使用類型註釋可以放在身邊的任何F#表達式,並指定表達式的類型 - 這你可以通過這種方式來暗示編譯器類型推理(通過說某些表達式具有特定類型)。如果您以某種巧妙的方式提供信息,編譯器將能夠確定Seq.cast的類型參數應該是什麼。舉幾個例子:

// By specifying type of the value 
let (res:seq<Match>) = Seq.cast v.Captures 

// By specifying return type of a function 
let getCaptures() : seq<Match> = 
    // ... 
    Seq.cast v.Captures 

// By specifying element type when iterating over the result 
for (m:Match) in Seq.cast v.Captures do 
    // ... 

從所有的選項,我認爲Brians(明確的)和我的第二個(函數的返回類型)是那些最地道的,但是,你可以選擇任何選項你發現最可讀的。