I've come up against this a couple of times, but I'm really at a loss as to why it happens.
I've got a discriminated union like:
type MStep<'A, 'B> =
| Shuttle of Quotations.Expr<'B> * Quotations.Expr<'B>
There's more to the union, but this shows the basic problem.
If I do:
let s1 = Shuttle(<@ l.SomeIntProp @>, <@ r.SomeIntProp @>)
let s2 = Shuttle(<@ l.SomeStrProp @>, <@ r.SomeStrProp @>)
I get a compiler error:
This expression was expected to have type int, but here has type string
Likewise, if I create them in the other order (string then int), I get the same error but the other way around.
I can see that the compiler is likely inferring 'B based on my usage, but what if I want 'B to be truly generic?
As requested here is a more complete example:
type MStep<'A, 'B> =
| Shuttle of Quotations.Expr<'B> * Quotations.Expr<'B>
| Ident of Quotations.Expr<'B>
| Trans of Quotations.Expr<'A> * Quotations.Expr<'B> * ('A -> 'B)
let doMig (f:Table<'A>, t:Table<'B>, s:('A * 'B -> MStep<'C, 'D> list)) =
ignore()
let a = doMig(bpdb.Adjustments, ndb.Adjustments, (fun (l,r) ->
[
Shuttle(<@ l.Id @>, <@ r.Id @>)
Shuttle(<@ l.Name @>, <@ r.Name @>)
]
))
This produces the compiler error as seen above.
NOTE:
bpdb and ndb are both database contexts provided by the SqlDataConnection type provider.
The open namespaces are:
open System
open System.Data
open System.Data.Linq
open Microsoft.FSharp.Data.TypeProviders
open Microsoft.FSharp.Linq
open System.Xml
open System.Xml.Linq
open Microsoft.FSharp.Quotations.Patterns
open System.Reflection
open System.Diagnostics
The problem is obvious here:
What exactly is the type of
t. The first element givesMStep<_,int> listand the second givesMStep<_,string>which are different.You can only put elements that are the same type into a list.