Compiler override type definitions (generics) in F #

Scenario 1

let map = Dictionary<string,obj>() map.Add("1",10) map.Add("2",10L) map.Add("3","10") 

It matches thin

Scenario 2

 let map = Dictionary<string,(unit -> obj)>() map.Add("1",fun() -> 10) map.Add("2",fun() -> 10L) map.Add("3",fun() -> "10") 

Here the compiler says that it excluded obj, but detected an int when it occurs 10

Scenario 3

 let map = Dictionary<string,(unit -> 'a)>() map.Add("1",fun() -> 10) map.Add("2",fun() -> 10L) map.Add("3",fun() -> "10") 

Here, the compiler accepts the first entry, but it causes a to be constrained by int, which is why the next two entries fail because they are not int

1st question: why does it compile in scenario 1 when it is not in scenario 2?

2nd question: Is there a way to prevent the 'restriction in scenario 3, or is there a specific template that can be used to include various types in the F # set (types of functions similar to this example)?

The only thing for which the values ​​(obj / 'a) should be used is the argument for println "%A" , which I do not see why this cannot be.

+4
source share
1 answer

In scenario 1, the compiler automatically map.Add argument from int , etc. to obj because he can see that map.Add expecting obj .

In scenario 2, he cannot do this because there is no update from unit -> int to unit -> obj - you could not do the conversion by manually inserting an upcast around the function.

Theoretically, the compiler can change the body of the function instead, but the automatic insertion of castings is purely local at the point where the map.Add call is map.Add .

You cannot stop it from being restricted in scenario 3, because the runtime requires certain objects to have a certain type - even if you only use values ​​in a certain way, the compiler and runtime do not execute which will be necessary for this.

+2
source

Source: https://habr.com/ru/post/1484440/


All Articles