Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

declaration-site variance annotations of generic type arguments #81

Open
maiermic opened this issue Apr 14, 2016 · 6 comments
Open

declaration-site variance annotations of generic type arguments #81

maiermic opened this issue Apr 14, 2016 · 6 comments

Comments

@maiermic
Copy link

Declaration-site variance annotations in other languages

C#, Kotlin, Ceylon:

  • out covariance
  • in contravariance

Scala, OCaml, Flow:

  • + covariance
  • - contravariance

What should we choose? (see discussion about generic types in #55 and #80)

@Mouvedia
Copy link
Collaborator

http://flowtype.org/docs/classes.html#polymorphism-and-type-parameter-variance

@maiermic
Copy link
Author

@Mouvedia Thx, I added Flow.

@Mouvedia
Copy link
Collaborator

Mouvedia commented Apr 14, 2016

https://github.com/Microsoft/TypeScript/wiki/FAQ#why-are-function-parameters-bivariant

Could you provide a JS example or a link to a ressource?

@ericelliott
Copy link
Owner

We handle polymorphism with the ability to use multiple signatures. Do we need variance annotations as well? Can you show some example usage and compare with multiple signature annotation to more clearly point out advantages or disadvantages?

What do variant annotations give us that we don't already have?

@maiermic
Copy link
Author

maiermic commented Apr 14, 2016

@Mouvedia This is the TypeScript example (of your link) that causes a runtime error:

function trainDog(d: Dog) { ... }
function cloneAnimal(source: Animal, done: (result: Animal) => void): void { ... }
let c = new Cat();
// Runtime error here occurs because we end up invoking 'trainDog' with a 'Cat'
cloneAnimal(c, trainDog);

As the author of the example states:

This is a unsoundness resulting from the lack of explicit covariant / contravariant annotations in the type system.

We shouldn't do the same fault as TypeScript. There are better ways. For example, this is the equivalent Scala code (run online):

abstract class Animal()
case class Dog() extends Animal
case class Cat() extends Animal

object Variance extends App {

  def cloneAnimal(source: Animal, done: (Animal) => Unit): Unit = {
    done(source)
  }

  def trainDog(dog: Dog): Unit = {}

  val cat = Cat()

  // causes compile error:
  cloneAnimal(cat, trainDog)
}

which results in a compile error

Error:(16, 20) type mismatch;
found   : Dog => Unit
required: Animal => Unit
cloneAnimal(cat, trainDog)
^

since Scala defines function parameters as contravariant: Function1[-T1, +R]. We should do the same to avoid runtime errors like in the TypeScript example, which is nothing else than JavaScript with type annotations that can be written in rtype.

@Mouvedia
Copy link
Collaborator

Mouvedia commented Apr 14, 2016

Ill give you a template for your straw-man proposal because for pure javascript developers it's really hard to grasp.

  1. signature with + and -
  2. signature with in and out (Covariance / Contravariance Annotations microsoft/TypeScript#1394)
  3. usage example (desired outcome)
  4. PROS of bivariant

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants