2
votes

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
1
I suspect there is some other code somewhere that is influencing this. Try to produce a minimal example to show the problem (do we need 'A? - John Palmer
Your example is still not complete. I can't paste your example in fsi and reproduce the error. Where is Table defined? Where is bpdb and ndb? Please include the namespaces you are opening as well. - Gus
I think it might even be an instance of the value restriction - if I simplify it to: type M<'a,'b> = M of Quotations.Expr<'b> it will produce those - Random Dev

1 Answers

7
votes

The problem is obvious here:

let t = [ //inserted t to have a concrete variable
    Shuttle(<@ l.Id @>, <@ r.Id @>); 
    Shuttle(<@ l.Name @>, <@ r.Name @>)
]

What exactly is the type of t. The first element gives MStep<_,int> list and the second gives MStep<_,string> which are different.

You can only put elements that are the same type into a list.