无法确定F#函数中的对象类型

时间:2015-08-27 15:48:16

标签: compiler-errors f# functional-programming

我在F#中有以下函数,不幸的是在我的折叠开头的Seq.filter中,w2Text(在比较中)没有标识Word类型。我不确定如何在这种情况下帮助编译器。编译器似乎对其他一切都很好。这是我第一次遇到这个问题。

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

2 个答案:

答案 0 :(得分: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

这样,statefolder中需要知道其类型之前发生,编译器可以“记住”该类型并在相关位置使用它。

这样,你的函数调用看起来像

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

folder函数调到Seq.fold后,没有进一步的参数。

(所有这些都归功于我从中学到的Ross McKinlay。)

答案 1 :(得分:2)

您可以添加类型注释:

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