Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Thanks for this question - it is a really nice bug report with a simple repro and I couldn't believe this, but you're completely right. Plus works, but minus doesn't.</p> <p><strong>The problem</strong> is that <code>sub</code> and <code>add</code> are compiled as generic methods and the LINQ version invokes these generic methods. The inlining is performed <em>after</em> quotations are stored, so the quoted code contains call to the <code>sub</code> method. This isn't a problem in normal F# code, because the functions are inlined and the operators are resolved to + or - over some numeric types.</p> <p>However, the generic version uses a dynamic lookup. If you look into <code>prim-types.fs:3530</code>, you'll see:</p> <pre><code>let inline (+) (x: ^T) (y: ^U) : ^V = AdditionDynamic&lt;(^T),(^U),(^V)&gt; x y when ^T : int32 and ^U : int32 = (# "add" x y : int32 #) when ^T : float and ^U : float = (# "add" x y : float #) // ... lots of other cases </code></pre> <p>The <code>AdditionDynamic</code> is what gets called from the generic method. It does the dynamic lookup, which will be slower, but it will work. Interestingly, for the minus operator, the F# library doesn't include dynamic implementation:</p> <pre><code>[&lt;NoDynamicInvocation&gt;] let inline (-) (x: ^T) (y: ^U) : ^V = ((^T or ^U): (static member (-) : ^T * ^U -&gt; ^V) (x,y)) when ^T : int32 and ^U : int32 = (# "sub" x y : int32 #) when ^T : float and ^U : float = (# "sub" x y : float #) // ... lots of other cases </code></pre> <p>I have no idea why this is the case - I don't think there is any technical reason, but it explains why you get the behavior you reported. If you look at the compiled code using ILSpy, you'll see that the <code>add</code> method does something and the <code>sub</code> method just throws (so this is where the exception comes from).</p> <p><strong>As for a workaround</strong>, you need to write the code in a way in which it doesn't use the generic minus operator. Probably the best option is to avoid <code>inline</code> functions (either by using <code>sub_int</code> or <code>sub_float</code>) or by writing your own dynamic implementation of <code>sub</code> (which can be done probably quite efficiently using DLR (see <a href="https://stackoverflow.com/questions/689240/how-is-the-upcoming-dynamic-keyword-in-net-4-0-going-to-make-my-life-better">this post</a>).</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload