tomprimozic / type-systems

Implementations of various type systems in OCaml.
The Unlicense
1.55k stars 71 forks source link

First class polymorphism + refined types? #2

Open FrankBro opened 10 years ago

FrankBro commented 10 years ago

First of all, I would like to say thank you for your great project on type systems. I've been interested in the concept for a while without never really touching or implementing them and your project really helps me to better understand them.

I've always thought that a perfect type system would be something along two of your sub-projects, first class polymorphism + refined types. I've been playing around with those two a little bit with the hope of merging them but I wanted to ask you first if it made sense since you seem to be well versed on the subject. Is there anything that would prevent them both from co-existing within the same type system?

tomprimozic commented 10 years ago

Hi! In theory, I don't see a problem, as the type inference/(ML) type-checking phase, which transforms the AST into a typed expression tree, and the refined type-checking (which makes sure that contracts are satisfied) are strictly separated. The problem, however, is that in the current implementation of the refined type system, functions as parameters are not implemented, and functions as return types are not fully implemented (hence, a lot of first-class polymorphism wouldn't pass the refined type checker because it would raise NotImplemented errors). I don't think it would be particularly hard to implement that, and it's completely orthogonal to first-class polymorphism, I'll probably implement it sometime soon.

But yes, I completely agree, a perfect type system would definitely support both refined types and first-class polymorphism (and hopefully other things as well, like a good record system).

FrankBro commented 10 years ago

Nice. I will continue playing with these two then and compare my version with yours if you decide to do it.

I agree, records and variants would be in indeed. Out of curiosity, is there any other specific features or properties your perfect type system would have? To me, a mix of ocaml/F# + type classes of haskell + easy to use dependent types sounds pretty perfect yea.

tomprimozic commented 10 years ago

Uh, that's a hard question... I'm still conflicted about it, as I haven't discovered yet how to even make some of the "perfect" parts of the "perfect" type system, let alone combine them. Some ideas:

FrankBro commented 10 years ago

linear/unique types that would enable (1) RIAA and safe I/O (i.e. you have to close every file)

Something like the indexed monad is really interesting here. Logic is type checked. https://gist.github.com/gelisam/9845116

(2) mutable updates of linear immutable structures

Something like functionally reactive?

(3) compiler optimizations (4) no GC (linear objects can be safely deallocated)

I was surprised F# didn't have something like list fusion in haskell. A typical functional pattern like folding creates new objects instead of modifying them, lifetime and usage isn't tracked. https://www.haskell.org/ghc/docs/7.0.1/html/users_guide/rewrite-rules.html

subtyping seems unavoidable for programming in the large; you need interfaces (Go) / abstract types (Julia) / traits (Scala) / classes (C++, Java). Also, "real math" has subtyping (i.e. an integer is a rational is a real is a complex). I hope to avoid it, but I haven't yet figured out how, especially since subtyping also gives you ...

Yea subtyping seems unavoidable.

records and first-class modules, ideally one system that can combine both. Type classes are nice, but seem to "magicky" - to make them really useful, you basically have to make it Touring-complete, which means a language within a language. I hope that modules + a kind of implicit arguments can make a simpler system for overloading/abstraction. But AFAIK no-one has done that so far.

I've had a problem for which type classes would've been nice not too long at work. It's just basically attaching interfaces but after a type definition. F# doesn't allow that, which forces you to write a bunch of boilerplate to contain types supported by the language (int, bool, string, etc).

dynamic types for when you just don't give a fuck

pls no

Apanatshka commented 10 years ago

Hi, just found this project through HN. Very cool!

I noticed this part of the discussion here:

I hope that modules + a kind of implicit arguments can make a simpler system for overloading/abstraction. But AFAIK no-one has done that so far.

I just wanted to share that long-term plans for Elm involve type-classy functionality which will likely be done with the already available (extensible) records and implicit arguments. I think one of the first mentions of this plan is here, and there are more references to records+Agda style implicit arguments on the mailing list. I know it's not quite the same as parametrised modules with implicit arguments, but I figured I'd share :)

tomprimozic commented 10 years ago

Hi Jeff!

Thanks for the pointer. I have a similar plan; combine combine records and implicit arguments to make type-classes. This is an interesting paper that I read on that topic: http://homepages.inf.ed.ac.uk/wadler/papers/implicits/implicits.pdf. I'm not sure it would work when combined with records or extensible records, but I think it's worth trying.

toroidal-code commented 10 years ago

Daan Leijen has an excellent paper that introduces an effect-based type system called LambdaK. The effect system is row-polymorphic, so multiple effects can be attributed to a single expression. There's an example implementation in Haskell for his language Koka.

toroidal-code commented 10 years ago

And I just saw your comment about Koka. Sorry!

arseniiv commented 6 years ago

union types, such as int | none or array[int | float]. They just seem so convenient. Of course, type inference becomes almost impossible (or at least nobody has figured it out yet, though I think it's implemented in Stardust).

Sorry, had stumbled on this thread by accident, I see there’s no recent activity here, but maybe you also would be interested in what was done about them in Ceylon. I haven’t read papers about its type system, but for example, they play nice there with contra/covariant type parameters. They also help there in encoding nonemptiness of streams and sequences and in typing tuples treated as heterogeneous lists (if I represent it correctly) and for representing types of argument lists containing optionals.