Coder Social home page Coder Social logo

List<Function> type resolution about sdk HOT 5 CLOSED

osaxma avatar osaxma commented on August 28, 2024
List type resolution

from sdk.

Comments (5)

lrhn avatar lrhn commented on August 28, 2024 1

Indeed, the graph is more like (restricting to only the types Never < int < Object?):

graph TD
    subgraph "Type hierarchy of int Function(int)"
        O("Object") --> F
        F("Function") --> ON
        ON("Object? Function(Never)") --> IN
        ON --> OI
        IN("int Function(Never)") --> NN
        IN --> II
        OI("Object Function(int)") --> II
        OI --> OO
        NN("Never Function(Never)") --> NI
        II("int Function(int)") --> NI
        II --> IO
        OO("Object? Function(Object?)") --> IO
        NI("Never Function(int)") --> NO
        IO("int Function(Object?)") --> NO
        NO("Never Function(Object?)") --> N           
        N("Never")
    end

In (covariant) return position, going from Object? to int to Never (or generally to a subtype) creates a subtype.
In contravariant parameter position, going from Never to int to Object?, or a any supertype, creates a subtype.

And it's all about what subtyping means: Substitutability. A value of the subtype must be usable where a value of the supertype is expected. A value of the subtype is-a value of the supertype, and satisfies all requirements that the supertype has.
For a function, that means it must return at most the same values as the supertype, and must accept at least the same arguments that the code might pass to the supertype.
Accepting more arguments is OK, someone expecting a supertype value won't be calling it with more than what the supertype accepts. Accepting fewer is not OK.
Returning fewer results (only ints and not fx num) is also OK, the supertype could return ints, so a caller will not be surprised.

from sdk.

lrhn avatar lrhn commented on August 28, 2024

When figuring out the element type of a list literal by looking at the type of the element expressions, the compiler attempts to find the least upper bound of the element expression types.

And it succeeds. Here, for 2a, it finds Object Function(Never), which is an upper bound of int Function (int) and String Function(String). (Not sure it's the last upper bound, since Comparable<Object> Function(Never) is lower, but it's good enough.)
And it is below Function, so it's a better approximation of the least upper bound than Function, so that's what the inference chooses.

For 2b, the type found by inference is again a supertype of both element expression types. You can test that both objects satisfy is Object Function(String).

So this is working as intended.

from sdk.

osaxma avatar osaxma commented on August 28, 2024

For 2b, the type found by inference is again a supertype of both element expression types. You can test that both objects satisfy is Object Function(String).

I think what confused me, and where I seem to have a misunderstanding, is how the function argument type is being resolved as a lower bound instead of an upper bound of the specified types.

For example, in the following cases, with my prior understanding, I would've expected the opposite for all of them:

print(((int x) => x) is Object Function(Object)); // prints false
print(((int x) => x) is Object Function(Never));  // prints true

print(((int x) => x) is Object Function(num));    // prints false
print(((num x) => x) is Object Function(int));    // prints true

In other words, this is the type lattice I had in mind when I was looking at it, and I assumed Object Function(Object), or Function, would be resolved:

graph TD
    subgraph "My Incorrect understanding"
        A(Object) --> B(Function)
        B --> C("Object Function(Object)")
        C --> D("int Function(int)")
        C --> E("String Function(String)")
        D --> F(Never)
        E --> F
    end

I would appreciate it if you would help me understand: why the type of the function argument seem to be resolved in different direction than that of the return type?

from sdk.

osaxma avatar osaxma commented on August 28, 2024

I think after reading about Covariance and contravariance (wikipedia), I understood that argument type in the Function constructor is contravariant which answers my previous question.

They also kindly mentioned in the article:

... programmers often find contravariance unintuitive

... and I had to agree with them 😅

Thanks a lot.

from sdk.

osaxma avatar osaxma commented on August 28, 2024

It's pretty clear to me know -- thanks a lot for the detailed explanation, @lrhn 🙏🏽

from sdk.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.