user6996876
user6996876

Reputation:

Tuples in where condition

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

Answers (2)

user6996876
user6996876

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

s952163
s952163

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

Related Questions