2015-08-27 32 views
2

我在F#中有下面的函數,不幸的是在我的摺疊開始處的Seq.filter中,w2.Text(在比較中)未標識爲Word類型。在這種情況下,我不確定如何幫助編譯器。編譯器在其他所有方面似乎都很好。這是我第一次遇到這個問題。無法確定F#函數中的對象類型

let CreateWordRelationDB() = 
    let db = new AnnotatorModel() 
    printfn "%s" "Entered Function and created db v7" 
    let tweets = db.Tweets 
       |> Seq.cast<Tweet> 
       |> Seq.map(fun t -> t.Text) 
    let words = db.Words |> Seq.cast<Word> 
    words 
    |> Seq.fold(fun acc w1 -> 
         let filtacc = acc 
             |> Seq.filter(fun w2 -> 
                 if(w1.Text = w2.Text) then false else true) 
         filtacc 
         |> Seq.map(fun w2 -> CreateWordRelation w1 w2 tweets) 
         |> Seq.iter(fun r -> db.WordRelations.Add(r) |> ignore) 
         db.SaveChanges() |> ignore 
         filtacc 
        ) words 
+0

如果您有任何共享等領域中使用的表達兩類這種情況通常只會發生,或者您使用的是類而不是記錄 - 由於諸如方法重載等類中的某些特性,編譯器無法推斷出這種類型。 –

回答

2

您可以添加類型標註:

|> Seq.filter(fun (w2: Word) -> if(w1.Text = w2.Text) then false else true) 
+1

哇,我是一個goon,我完全忘了我可以把功能放在那個點上... –

+0

我傾向於把註釋放在最接近它需要的地方,例如, '(W2:字).Text'。我不確定這是否被認爲是好的做法或習慣用法,但這確實意味着如果註解的原因被移除,那麼註釋可能會隨着它而被移除,而不是被遺忘爲混亂。 – TheQuickBrownFox

+0

可以簡化一下:|> Seq.filter(fun(w2:Word) - > w1.Text <> w2.Text) –

5

有一個 - 可以說 - 不是使用類型註釋更優雅的方式。

這裏的問題是非F#類型的類型推斷(其實際上是Word)不如F#record/DU類型強大。如果相應的值出現在之前的代碼之前,那麼編譯器只能推斷它們的類型(因此它沒有那麼多的推理,但更多的「類型跟蹤」)。

您正在以這種方式使用foldsource |> Seq.fold folder state

所以state,爲此型仍然需要確定,則folder功能,它被使用之後發生。但是,您可以在該點之前使用不熟悉的||>運算符來移動它。

這個操作符被定義爲let inline (||>) (a, b) f = f a b,並允許您咖喱兩個獨立的參數「到」功能:(state, source) ||> Seq.fold folder

這樣,state其類型的知識之前發生,需要在folder,編譯器可以「記住「類型並在相關的地方使用它。

就這樣,你的函數調用看起來像

(words, words) // The first is the state, the second the source 
||> Seq.fold (fun acc w1 -> ... // long folder function) 

咖喱到Seq.foldfolder功能後,沒有進一步的說法。

(這一切歸功於羅斯麥金利誰,我學會了這從。)

+0

非常整齊。這就是爲什麼我有時會閱讀F#源代碼,找到這樣的東西。 – statue

相關問題