f# - Type inference wants explicit upcast sometimes even when flexible type is used for interface constraints? -


I hoped that the flexible type would reduce the need for explicit exception, but

  IB = Sulfur B: Int Type A () = Interface with IB member. B = 1 Let's do a = A () Let's test (x) = let's aa = [| A; One |] Let's Cause 1 = AA | & Gt; Array.map (fun (x: #IiB) - & gt; Test (xb)) Case 2 = Array.map (Fun (X: #IB) -> Test (xb)) A   

Here, the warnings on the last 2 lines (less generic than type annotations) are compiling the compiler case2 , but fails in case1 Why is it like this?

It seems weird that a more detailed compiler can guess, I need more code to write.

@KVB said that there is a simple fix, just to refurbish the lambda function in a non inline version.

  X: # IB) = test xB give case1 = aa | & Gt; Set Array.map case2 = Array.map fix   

This works well.

Type the estimate in the F # flux from left to right, so it is not surprising that piping Can break or cure. However, this is almost always the case that more types of information are already helpful, so the result is a little surprising. Alerts are a subtle indicator that you are doing something wrong. Flexible type looks like they should be applied in many difficult situations, but in fact there are only a few places where they help. Array.map does one of several types of functions 'a - & gt; For some special 'a and ' b ' (though there is a bit subtlety, because "special type" types can be type variables), Therefore, a "more general" logic is being made like "code" #IB -> Int is not particularly helpful; During the compiler collection, some subtypes of IB will be selected - this is what is attempting to communicate the warning.

As I said, the different results you are seeing on different lines are the fact that in the first case left in order to correct the type of guesses in the F # type, aa The type of expression flows in check and hence while compiling lambda, the compiler knows that IB will work A but because Interface implementation is always included, This is a compilation time error reason because A is not a publicly available member B . On the other hand, in the second case, when the compiler is trying to check Array.map , it does not know the type of array that it will be applied to, but any call can be checked The case may be, because regardless of the subtype, it will support the interface method IB.B (which should raise the argument by the subtype of IB , only it is IB ). Then when it applies to aa , the implementation is applied to A , but due to dissatisfaction it still works fine. Generally, it seems that the compiler should be able to put the same underlying turbulence in the first case, but I think this estimate is just a surprising result of the algorithm and not the actual bug.

Probably more surprising, a potential fix is ​​just an inherent definition (either for Lambda or even as a type-restricted version of Array.map ) To use the flexible type:

  f (x: IB) = test (xb) (F: IB -> int) = array.map f D = AA | & Gt; G (Fun x -> Test (xb)) Let's D '' = AA | & Gt; Array.map f let c '= g (fun x -> test (x.b)) come c' '= array.map FA   

So what's going on here? It turns out that the compiler does something called "Insertion of Flexibility for Function and Use of Members" (Section 14.4.3 of the class for F # 3.1), which is exactly what you want.

Comments

Popular posts from this blog

java - ImportError: No module named py4j.java_gateway -

python - Receiving "KeyError" after decoding json result from url -

.net - Creating a new Queue Manager and Queue in Websphere MQ (using C#) -