Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is type inference impractical for object oriented languages?

I'm currently researching ideas for a new programming language where ideally I would like the language to mix some functional and procedural (object oriented) concepts.

One of the things that I'm really fascinated about with languages like Haskell is that it's statically typed, but you do not have to annotate types (magic thanks to Hindley-Milner!).

I would really like this for my language, however after reading up on the subject it seems that most agree that type inference is impractical/impossible with subtyping/object orientation, however I have not understood why this is. I do not know F#, but I understand that it uses Hindley-Milner AND is object-oriented.

I would really like an explanation for this and preferably examples on scenarios where type inference is impossible for object oriented languages.

like image 763
monoceres Avatar asked Mar 20 '14 09:03

monoceres


People also ask

What is inference in oops?

Type inference or deduction refers to the automatic detection of the data type of an expression in a programming language. It is a feature present in some strongly statically typed languages.

What languages have type inference?

Some languages that include type inference include C++11, C# (starting with version 3.0), Chapel, Clean, Crystal, D, F#, FreeBASIC, Go, Haskell, Java (starting with version 10), Julia, Kotlin, ML, Nim, OCaml, Opa, Q#, RPython, Rust, Scala, Swift, TypeScript, Vala, Dart, and Visual Basic (starting with version 9.0).


2 Answers

To add to seppk's response: with structural object types the problem he describes actually goes away (f could be given a polymorphic type like ∀A ≤ {x : Int, y : Int}. A → Int, or even just {x : Int, y : Int} → Int). However, type inference is still problematic.

The fundamental reason is this: in a language without subtyping, the typing rules impose equality constraints on types. These are very nice to deal with during type checking, because they can usually be simplified immediately using unification on the types. With subtyping, however, these constraints are generalised to inequality constraints. You cannot use unification any more, which has at least three unpleasant consequences:

  1. The number and complexity of constraints explodes combinatorially.
  2. The information you have to display to the user in case of errors is incomprehensible.
  3. Certain forms of quantification can quickly become undecidable.

Thus, type inference for subtyping is not impossible (there have been many papers on the subject in the 90s), but it is not very practical.

A much simpler alternative is employed by OCaml, which uses so-called row polymorphism in place of subtyping. That is actually tractable.

like image 155
Andreas Rossberg Avatar answered Oct 16 '22 08:10

Andreas Rossberg


When using nominal typing (that is a typing system where two classes whose members have the same name and the same types are not interchangeable), there would be many possible types for a method like the following:

let f(obj) =
    obj.x + obj.y

Any class that has both a member x and a member y (of types that support the + operator) would qualify as a possible type for obj and the type inference algorithm would have no way of knowing which one is the one you want.

In F# the above code would need a type annotation. So F# has object orientation and type inference, but not at the same time (with the exception of local type inference (let myVar = expressionWhoseTypeIKNow), which always works).

like image 6
sepp2k Avatar answered Oct 16 '22 09:10

sepp2k