我在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
答案 0 :(得分:5)
有一种 - 可以说 - 比使用类型注释更优雅的方式。
这里的问题是非F#类型(Word
本质上是)的类型推断不如F#record / DU类型强大。如果相应的值出现在代码之前使用它的位置,编译器只能推断出那些类型(所以它不是那么推断而是更多的“类型跟踪”)。
您以这种方式使用fold
:source |> 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)
folder
函数调到Seq.fold
后,没有进一步的参数。
(所有这些都归功于我从中学到的Ross McKinlay。)
答案 1 :(得分:2)
您可以添加类型注释:
|> Seq.filter(fun (w2: Word) -> if(w1.Text = w2.Text) then false else true)