Why does declaration order matter for generic members?

Asik

Today I noticed that the following does not compile:

open System

type MyType() =        
    member this.Something() =
        this.F(3)
        this.F("boo") 
        //     ^^^^^
        // This expression was expected to have type 'int' but here has type 'string'
        
    member private this.F<'T> (t:'T) =
        //                ^^
        // This type parameter has been used in a way that constrains it to always be 'int'
        // This code is less generic than required by its annotations because the explicit type variable 'T' could not be generalized. It was constrained to be 'int'.
        Console.WriteLine (t.GetType())

But simply change the declaration order, and there's no problem.

open System

type MyType() =        
    member private this.F<'T> (t:'T) =
        Console.WriteLine (t.GetType())
        
    member this.Something() =
        this.F(3)
        this.F("boo")

This took me a long while to figure out as I didn't expect declaration order to matter for members of a class. Is this expected behavior?

Tomas Petricek

This is a subtle side-effect of how the F# type inference works. I do not think there is a better workaround for the issue than reordering your definitions.

To provide more background, the members of a class are automatically treated as mutually recursive (meaning that they can call each other). Unlike with multiple types or multiple functions in a module, you do not need to declare this explicitly using the rec keyword.

However, the issue is not limited to classes. You can get exactly the same behaviour with simple functions. The simplest possible example is:

let rec test() = 
  f 3       // Warning: causes code to be less generic
  f "boo"   // Error: string does not match int
and f (arg:'a) = ()

In the opposite order, this works just fine:

let rec f (arg:'a) = ()
and test() = 
  f 3
  f "boo"

The issue is that the type-checker analyzes the code from top to bottom. In the first case, it:

  • Sees f 3 and infers that f is of type int -> unit
  • Sees f "boo" and reports a type error
  • Sees f (arg:'a) and realizes it prematurely used a more specific type than needed (and reports the various warnings).

In the second case, it:

  • Sees f (arg:'a) and infers that f is of type 'a -> unit
  • Sees f 3 and f "boo" and uses appropriate type instantiation

The main reason for why the type checker cannot be more clever is that the type checker only does "generalization" (i.e. figures out that a function is generic) after it analyzes the whole body of the function (or the whole recursive block). If it encounters a more specific use inside the body, it never gets to this generalization step.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

Why does declaration order matter for generic members?

From Dev

Why does order in method declaration matter?

From Dev

Why does order in method declaration matter?

From Java

Does the order of members in a struct matter?

From Dev

Why does the order of the before_actions declaration matter?

From Dev

Why does order of declaration matter for annotated global variables in modules?

From Dev

Why does the order of the before_actions declaration matter?

From Dev

Does the function declaration order matter in a header file?

From Dev

Does the function declaration order matter in a header file?

From Dev

Does the order of instance variable declaration matter in Objective-C?

From Dev

Does order of service declaration matter when creating them in a module?

From Dev

Does function declaration order matter in ES6?

From Dev

Why does the order of css selectors matter?

From Java

Why does order of mutable borrows matter in Rust?

From Dev

Pandas: Why does order of selection matter?

From Dev

Why does the order of template argument substitution matter?

From Dev

Order of calling methods - why does it matter in this example?

From Dev

Why does this library dlopen order matter?

From Dev

why does the order of variable declaring matter?

From Dev

why does order of loop nesting matter python?

From Dev

Why does the order of alternatives matter in regex?

From Dev

Why does the order of applying advice matter?

From Dev

why does the order of variable declaring matter?

From Dev

why does order of loop nesting matter python?

From Dev

Why does the order of prerequisites matter in a makefile?

From Java

Does annotations order matter?

From Dev

Does order of conditions in $and matter?

From Dev

Why one child class alone flings error ? does order matter?

From Dev

why does order matter in this escaped characters class in sed?

Related Related

  1. 1

    Why does declaration order matter for generic members?

  2. 2

    Why does order in method declaration matter?

  3. 3

    Why does order in method declaration matter?

  4. 4

    Does the order of members in a struct matter?

  5. 5

    Why does the order of the before_actions declaration matter?

  6. 6

    Why does order of declaration matter for annotated global variables in modules?

  7. 7

    Why does the order of the before_actions declaration matter?

  8. 8

    Does the function declaration order matter in a header file?

  9. 9

    Does the function declaration order matter in a header file?

  10. 10

    Does the order of instance variable declaration matter in Objective-C?

  11. 11

    Does order of service declaration matter when creating them in a module?

  12. 12

    Does function declaration order matter in ES6?

  13. 13

    Why does the order of css selectors matter?

  14. 14

    Why does order of mutable borrows matter in Rust?

  15. 15

    Pandas: Why does order of selection matter?

  16. 16

    Why does the order of template argument substitution matter?

  17. 17

    Order of calling methods - why does it matter in this example?

  18. 18

    Why does this library dlopen order matter?

  19. 19

    why does the order of variable declaring matter?

  20. 20

    why does order of loop nesting matter python?

  21. 21

    Why does the order of alternatives matter in regex?

  22. 22

    Why does the order of applying advice matter?

  23. 23

    why does the order of variable declaring matter?

  24. 24

    why does order of loop nesting matter python?

  25. 25

    Why does the order of prerequisites matter in a makefile?

  26. 26

    Does annotations order matter?

  27. 27

    Does order of conditions in $and matter?

  28. 28

    Why one child class alone flings error ? does order matter?

  29. 29

    why does order matter in this escaped characters class in sed?

HotTag

Archive