Out of curiosity, did you try Typed Clojure? It certainly has its rough edges, but you sound willing to bear the burden of annotating code with types (at the top-level, at least) and I *think* its treatment of Java interop does what you want: unless instructed otherwise, the typechecker assumes that arguments to Java methods must not be nil and that any Java method may return nil.
On Thursday, October 20, 2016 at 8:39:04 AM UTC-4, Colin Fleming wrote: > > I recently spent a bunch of time researching exactly this. My motivation > was that my main project, Cursive, suffers from a ton of NPEs which I find > very difficult to manage. I wanted to see how difficult it would be to have > a typed Clojure-like thing, using something similar to Kotlin's type > system. Kotlin uses a type system which is similar to Java and has Java > interop as a primary goal, which I would also need since Java interop is > essential to me. It fixes a bunch of flaws in the Java type system and adds > new features like nullable types, which I now find it difficult to live > without. > > Before anyone asks, spec is not useful for me because it relies heavily on > generative testing to increase your confidence in your functions. I can't > use generative testing because my application is tied to a large Java > codebase which I cannot model to any useful degree. Essentially, spec > recommends runtime tests at the boundary of your system, and nearly my > entire system is interop boundary. I'm not interested in runtime checks > except where absolutely necessary - Kotlin does this for me transparently, > spec doesn't. > > Here's a short list of my findings. I'm happy to expand on any of these > points if anyone is curious. It bears repeating - Java interop is > non-negotiable for me, and that makes a lot of this harder than it would be > otherwise. > > Disclaimer: I'm no programming language expert. This was hard for me, and > a surprising amount of it was new to me. I'd appreciate any corrections or > clarifications. > > 1. Type systems are hard. I for one didn't appreciate the complexity > that goes into making them easy to use. Don't be fooled by the 20-line > implementations of Hindley-Milner. > 2. In particular, generics are very hard, and variance for generic > objects (i.e. the intersection of generic objects and OO) is the source of > much difficulty. > 3. Type systems are split into two main camps - nominal typing (like > Java, where the types are identified by names) and structural typing, > where > the type of an object is defined by it's "shape", like Go's interfaces. > 4. One of the major benefits of Clojure is its heterogeneous > collections, a.k.a. "just use a map". This is very difficult to maintain > in > a type-safe manner without losing most of the benefit. > 5. There are two main things I was interested in from a type system - > type checking (i.e. making sure that your program's types are correct) and > type inference (working out what the types of things are from the code, so > you don't have to annotate everything). Type checking is relatively > straightforward, but type inference can be very hard indeed. > 6. Much of the complication comes from the need to interop with Java. > ML-style interface essentially doesn't work if you want to maintain > compatibility with Java since it cannot be interfaced in a useful way with > nominal OO systems. In particular, method overriding is basically > impossible to represent. > 7. #6 implies that you cannot have a language with good Java interop > *and* global type inference, i.e. you will definitely be annotating > your function parameter types, and your function return types. I'm ok with > this since IMO it's a good practice anyway. > 8. Once you start thinking about the fact that you no longer have > heterogeneous collections, and start thinking about what the alternatives > would look like, you start to realise that you'd end up with basically the > ML family style of data types - homogeneous collections, typed tuples and > ADTs. I'm actually ok with that too, since they're a very nice set of > primitives and I think they probably represent 95% of how people use > Clojure's collections anyway. > 9. Structural typing seems like it might be a good fit for something > like Clojure's maps. However, mixing structural and nominal typing > *and* OO seems to be the path to madness. > > I think that's it. This is still a project I'd like to tinker with at some > point, but I think it's fair to say that I dramatically underestimated the > amount of work a useful Java-compatible type system would be. I still think > it seems like a nice point in the language design space though, which is > curiously unfilled on the JVM (some of you may have noticed that I > basically want F# with nullable types). > > Cheers, > Colin > > On 16 October 2016 at 00:14, Didier <did...@gmail.com <javascript:>> > wrote: > >> I know a lot of people like to say how unhelpful Java like static typing >> is, and only more powerful type systems of the ML family add value, but >> I've been wondering recently if for Clojure it wouldn't make more sense to >> simply extend the type hints to enable an optional Java like static typing >> scheme. >> >> It is my understanding that ML style static typing is incredibly >> difficult to add properly and without compromise to a dynamic language. >> That doing so limits the scope of type inference, rendering the task of >> adding type info more tedious then in ML languages themselves. >> >> ML style static typing provide enhanced safety grantees, but seem to add >> too much complexity to Clojure to be practical. What about a Java like >> static typing scheme though? >> >> I haven't found in practice that the safety of Clojure was an issue, as >> the REPL workflow tend to promote quite a lot of testing. So I'm not too >> worried about needing the state of the art of provable correctness for my >> programs. What has been a biggest cause of issue to me was refactoring and >> shared code base across a team. Those last two use cases are actually >> pretty well handled by Java like static type checking. Is it a powerful >> type checker, not really, but it enables most trivial type errors to be >> caught early, and it allows easier integration points for other devs to >> follow, as well as documentation for functions, better tools support and >> easier refactoring, while also enabling performance optimizations. >> >> I have limited knowledge in typing systems, and have no idea how easy it >> is to implement them, but as a user of Clojure, I feel like I would find an >> optional Java like static typing a great addition, one that I am more >> willing to use and benefit from then Typed Clojure's more complex ML style >> type checking. >> >> What do other think? >> Can anyone with better knowledge tell me if this would be feasible or if >> adding such gradual typing system is effectively as hard as adding ML style >> type checking? >> >> -- >> You received this message because you are subscribed to the Google >> Groups "Clojure" group. >> To post to this group, send email to clo...@googlegroups.com >> <javascript:> >> Note that posts from new members are moderated - please be patient with >> your first post. >> To unsubscribe from this group, send email to >> clojure+u...@googlegroups.com <javascript:> >> For more options, visit this group at >> http://groups.google.com/group/clojure?hl=en >> --- >> You received this message because you are subscribed to the Google Groups >> "Clojure" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to clojure+u...@googlegroups.com <javascript:>. >> For more options, visit https://groups.google.com/d/optout. >> > > -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.