top | item 43514423

(no title)

paldepind2 | 11 months ago

> Wait, if I recall correctly, covariance has long been established as a mistake.

Perhaps you're just missing some words here, but, just for clarity: it doesn't make any sense to say that covariance is a mistake. Covariance applied in specific places, like Java's mutable covariant arrays which leads to unsoundness, can be a mistake, but covariance itself in fine and essential in languages with subtyping. Function parameters should be covariant, function returns should be contravariant, mutable data structures should be invariant, etc.

discuss

order

pansa2|11 months ago

> function returns should be contravariant

I'm not very familiar with these relations, but shouldn't function returns be covariant? `String => Cat` is a subtype of `String => Animal`?

> Function parameters should be covariant

For function parameters, doesn't it depend on how the parameter is used?

paldepind2|11 months ago

> I'm not very familiar with these relations, but shouldn't function returns be covariant? `String => Cat` is a subtype of `String => Animal`?

You're right :) I mixed up covariance and contravariance for function parameters and return value in my comment.

> For function parameters, doesn't it depend on how the parameter is used?

I don't think so, but maybe there's specific circumstances I don't know of? Function parameter types is a constraint on _input_ to the function. Changing that to a subtype amounts to the function receiving arguments that satisfies a stronger constraint. That seems that something that would hold no matter how the parameter is used?

sparkie|11 months ago

`String => Cat` and `String => Animal` are the types of the functions themselves - not the arg and return types.

If we consider inside the function:

    foo : arg:String => result:Animal
    foo = 
        ;; arg <: String
        ;; Animal <: result
However, outside of the function, when calling it, the opposite is true.

    let result = foo (arg)
        ;; String <: arg
        ;; result <: Animal
It's easy to get them mixed up when looking at it from the wrong perspective - but we should be looking at functions from the outside, not the inside - so yes, parameters should be contravariant and return types covariant.