Reputation:
Given that in F#
Tuples have an automatically defined equality operation
and therefore
let myQueryable = [| (1, 1); (2,2)|].AsQueryable()
let check =
query {
for x in myQueryable do
} |> Seq.where(fun x -> x = (2,2))
is {(2,2)}
, then why
let check =
query {
for x in myQueryable do
where(x = (2, 2))
}
is Empty
?
Upvotes: 2
Views: 280
Reputation:
It seems a compatibility issue between C# System.Tuple
and F# reference tuples.
It is interesting that the compatibility issue seems to be solved between C# 7 and F# 4.1 with the new ValueTuple
equivalent to F# struct tuples.
let myQueryableNew = [| ValueTuple.Create(1, 1); ValueTuple.Create(2,2) |].AsQueryable()
let resultFSharp1 =
query {
for x in myQueryableNew do
} |> Seq.where(fun x -> x = ValueTuple.Create(2,2))
let resultFSharp2 =
query {
for x in myQueryableNew do
where (x.Equals(ValueTuple.Create(2, 2)))
}
Btw, notice also that the new type has a more coherent default (in case of this related issue)
let testDefault =
query {
for x in myQueriable1 do
where (x.Equals(ValueTuple.Create(1, 2)))
select x
headOrDefault
}
Upvotes: 1
Reputation: 6324
You probably have System.Linq
open.
The following returns (2,2)
for me in both cases:
//open System
//open System.Linq
let myQueryable = [| (1, 1); (2,2) |] //.AsQueryable()
let check =
query {
for x in myQueryable do
select x
} |> Seq.where(fun x -> x = (2,2))
check //val it : seq<int * int> = seq [(2, 2)]
let check' =
query {
for x in myQueryable do
where (x = (2, 2))
select x
}
check' //val it : seq<int * int> = seq [(2, 2)]
So within an IQueryable
this structural equality doesn't hold. I don't know if it's because of the IQueryable type, i.e. it becomes reference equality, or where
gets redefined, or a possible bug.
Upvotes: 0