I asked the following question on hubfs.net

This might be a newbie question about type inference, but it can help beginners like me.

I am using the query below – which sorts items by date. This gives the warning: This lookup uses a deprecated feature, where a class type is inferred from the use of a class field label…

Query.query <@ (Seq.sort_by (fun i -> i.DateAdded) (seq { for item in ctx.BarterItems do yield item }))   |> Seq.take 50 @>;

In the seq { … } expression, the type of item is identified as “Item” correctly, through ctx.BarterItems. Why wouldn’t this be used to infer “i” in “fun i -> i.DateAdded“? ; Seq.sort_by being (<’a>-><’key>) -> seq<’a> -> seq<’a>

Explicitly identifying the type will remove the warning, as below:
Query.query <@ (Seq.sort_by (fun (i:Item) -> i.DateAdded) (seq { for item in ctx.BarterItems do yield item }))   |> Seq.take 50 @>;

Brian McNamara pointed out:

Type inference in F# works left-to-right through an expression; for example

let s = seq { yield “foo”; }

let s2 = s |> Seq.sort_by (fun x -> x.Length) // compiles

//let s2 = Seq.sort_by (fun x -> x.Length) s // does not

In the first one, we already know that the elements of ’s’ are type ’string’ by the time we reach the lambda body and “x.Length”.  In the second one, we don’t.  This is one of the things that makes the pipelining style so attractive.

As Brian pointed out, thats a good use case for the Pipelining operator.

My new query looks like:
Query.query <@ seq { for item in ctx.BarterItems do if item.ItemType = "book" then yield item }
|> Seq.sort_by (fun i -> i.DateAdded) |> Seq.take 50 @>;

Inference now works, since the type can be inferred left to right.

Meanwhile you can read more on ML type inference.

Leave a Reply