News for hackers. Stuff that matters.
Re:What is Hindley-Milner and why is it cool? (2008) by Animats on Sunday August 20, 2017 @02:28PM (#15059600)
The trend seems to be for languages to have forward inference of types within functions, while declaring them in function definitions. Assignments which initialize a variable also implicitly declare its type. C++ started this with "auto", but it's really because programmers had become used to dynamic languages where assignment set type. Go and Rust both do this.

Inferring types of function parameters and results isn't as useful. Combined with generics, it gets really complicated. It seems better to have those declared explicitly. Programmers need to be able to read function signatures when programming. They're an essential part of the documentation. Also, whole-program type inference and separate compilation inherently conflict.

That's pretty much where things seem to be settling out. Even Python now has optional type declarations for function signatures.

Re:What is Hindley-Milner and why is it cool? (2008) by dbaupp on Sunday August 20, 2017 @04:34PM (#15060128)
> The trend seems to be for languages to have forward inference of types within functions, while declaring them in function definitions. Assignments which initialize a variable also implicitly declare its type. C++ started this with "auto", but it's really because programmers had become used to dynamic languages where assignment set type. Go and Rust both do this.

Note that this is quite different to, and simpler than, HM inference. It doesn't require unification like the article describes and is something all statically typed languages practically have to do anyway: even with full annotations, validating `T x = f()` (or equivalent) requires type checking the `f()` expression to see that it actually is a T. And thus, this style of "inference" can be gained by simply not requiring the T type to be written and just taking the result of type checking `f()` as gospel, and is what C++ and Go do. (There's a bunch of subtlety/complexity for this in C++, but that's due to C++, not this form of "inference".)

Proper HM (or similar) type inference will use information from how variables are manipulated after their declaration to decide on the type, and so is more than what's already done for the purposes of type checking. This is what Rust does, breaking the supposed trend.

Re:What is Hindley-Milner and why is it cool? (2008) by vilhelm_s on Sunday August 20, 2017 @04:47PM (#15060179)
Although even with local type inference you usually want to do some unification based inference also, at least to infer the type arguments for generic functions. But it's still simpler than inferring the most general types for functions themselves.
Re:What is Hindley-Milner and why is it cool? (2008) by lambdawitch on Sunday August 20, 2017 @03:18PM (#15059820)
> Inferring types of function parameters and results isn't as useful. Combined with generics, it gets really complicated.

I wonder why you think so? The inferred types in a language like Haskell or OCaml are almost always exactly what the programmer would have written. So long as a language has principle type inference, the worst case is that the inferred type is a bit more general than you expected.

> Also, whole-program type inference and separate compilation inherently conflict.

There is no conflict here, actually. All type variables in definitions exported from a module are generalizable. As such, no uses in other modules will further refine those types.

Re:What is Hindley-Milner and why is it cool? (2008) by dtech on Sunday August 20, 2017 @03:45PM (#15059935)
> I wonder why you think so? The inferred types in a language like Haskell or OCaml are almost always exactly what the programmer would have written

I have no experience with ML-using languages but in Scala, which has inferior but still useful type inference, it is recommended to add explicit types to public functions/methods because otherwise, implementation details or errors might alter the signature.

Take for example:

    data Tree = Node Leaf Leaf | Leaf Integral
    makeEmptyTree x => Leaf x
I assume `Leaf` will be inferred as a type, while the programmer might have meant `Tree` to be the public API. (or vice-versa)
Re:What is Hindley-Milner and why is it cool? (2008) by catnaroek on Sunday August 20, 2017 @03:59PM (#15059988)
In ML, constructors aren't subtypes of a sum type. And that's a good thing.
Re:What is Hindley-Milner and why is it cool? (2008) by tel on Monday August 21, 2017 @07:00AM (#15063578)
This is largely to do with subtyping and it's well known that systems with user-defined nominal subtyping don't have good inference. Scala's inference is really in the middle: squarely better than C/Java and much worse than Haskell/OCaml.
Re:What is Hindley-Milner and why is it cool? (2008) by pdexter on Sunday August 20, 2017 @03:55PM (#15059973)
No, Leaf isn't a type.
Re:What is Hindley-Milner and why is it cool? (2008) by 1wd on Sunday August 20, 2017 @06:05PM (#15060477)
C# had "var" since 2007. C++ "auto" is from 2011?

https://en.wikipedia.org/wiki/C_Sharp_3.0#Local_variable_typ...

Re:What is Hindley-Milner and why is it cool? (2008) by archgoon on Sunday August 20, 2017 @03:59PM (#15059987)
>> C++ started this with "auto",

C++ most certainly did not start this. It had been in ML (orginally developed by Robin Milner) for decades. It has been a feature of every ML derived language, and Scala had it back in 2004.

Re:What is Hindley-Milner and why is it cool? (2008) by weinzierl on Sunday August 20, 2017 @04:20PM (#15060082)
I think Animats was referring to the

> forward inference of types within functions, while declaring them in function definitions.

part, not type inference in general.

Re:What is Hindley-Milner and why is it cool? (2008) by tpush on Sunday August 20, 2017 @03:09PM (#15059792)
Requiring type annotations on all functions would make programming with higher order functions very laborious.

I'd agree if we're talking about top-level only, though.

Re:What is Hindley-Milner and why is it cool? (2008) by kristianp on Sunday August 20, 2017 @05:39PM (#15060376)
Things are "settling out" at that stage with non-ML-derived languages because that it the most inference you can get without going full Hindley-Milner. It doesn't mean that inferring types of function parameters and return values isn't as useful.
Re:What is Hindley-Milner and why is it cool? (2008) by guelo on Monday August 21, 2017 @01:51PM (#15066248)
I don't really like where type inference is settling out. Maybe it does come from programmers becoming used to dynamic languages but it doesn't mean it's better.

I find

  val x = fn()
to be almost maliciously hiding the type when

  int x = fn()
is just as simple and gives you much more information, especially when reading code outside an IDE such as on github. val/let/def and the like are just low information cruft.

A lot of times I'll find myself creating an extra local variable just to have the type info in the variable name since otherwise it's invisible from just reading the code. Essentially adding an extra unchecked type system layer I have to manually maintain:

  val listOfThings = functionThatHopefullyReturnsThings()
Re:What is Hindley-Milner and why is it cool? (2008) by goatlover on Sunday August 20, 2017 @05:55PM (#15060435)
But then again, Julia is a relatively new language that aims for high performance in scientific computing while using type inference. Helps to have multiple dispatch that tells you how many definitions there are for a function.
Re:What is Hindley-Milner and why is it cool? (2008) by tbenst on Sunday August 20, 2017 @06:02PM (#15060467)
Julia however does not use Hindley-Milner[1]. I'm under the impression that HM is not compatible with multiple dispatch, which would be very unfortunate as typeclasses can serve the same purpose while maintaining compatibility with HM.

[1] https://stackoverflow.com/questions/28078089/is-julia-dynami...

Re:What is Hindley-Milner and why is it cool? (2008) by vram22 on Sunday August 20, 2017 @06:36PM (#15060584)
>C++ started this with "auto"

D also has this.

https://dlang.org/spec/declaration.html#AutoDeclaration

Re:What is Hindley-Milner and why is it cool? (2008) by jackmott on Sunday August 20, 2017 @02:38PM (#15059644)
if the editor is aware of the type inference, you can display the signature without having to type it. it can be useful as you get automatically generic functions, which can save a lot of time if you decide the refactor later and use say, floats instead of doubles. you don't have to edit any functions. just start using floats.
Re:What is Hindley-Milner and why is it cool? (2008) by Animats on Sunday August 20, 2017 @02:49PM (#15059691)
if the editor is aware of the type inference

Does any actual editor do that? Few text editors for programs are even aware of definitions in other modules.

Re:What is Hindley-Milner and why is it cool? (2008) by somenewacc on Sunday August 20, 2017 @05:22PM (#15060312)
For Haskell, there's a plugin called ghc-mod

http://www.mew.org/~kazu/proj/ghc-mod/en/

It works with many text editors, like Emacs or vim.

edit: the trend today is to work with the "language server protocol":

http://langserver.org/

Haskell people are writing new tooling based on LSP to supersede ghc-mod:

https://github.com/alanz/haskell-lsp

Re:What is Hindley-Milner and why is it cool? (2008) by w4tson on Monday August 21, 2017 @01:25PM (#15066072)
Is this what rust uses in IntelliJ? I know they have built some tooling that IDEs delegate to for tooling such as autocomplete etc rather than building it n times in n editors
Re:What is Hindley-Milner and why is it cool? (2008) by steveklabnik on Monday August 21, 2017 @02:42PM (#15066664)
IntelliJ has their own stuff, it does not use the RLS.
Re:What is Hindley-Milner and why is it cool? (2008) by paavohtl on Sunday August 20, 2017 @03:08PM (#15059776)
Any editor or IDE with F# or TypeScript support can show the inferred type for anything you have selected or hover over. Ionide (an F# plugin for VS Code) can even show the inferred type over each let binding (including functions) within the text editor itself.
Re:What is Hindley-Milner and why is it cool? (2008) by Groxx on Sunday August 20, 2017 @03:56PM (#15059982)
I dare say we can call this "yes, for many popular languages, in many modern IDEs".

Might I suggest taking a fresh look at IDEs? It sounds like you might be stuck in text-editor land, wondering how green the grass is on the other side (or if they even have grass). IDEs do indeed provide grass, and a significant portion of the time it'll even trim and weed itself when you look at it and wonder if it's time to mow.

Re:What is Hindley-Milner and why is it cool? (2008) by tomjakubowski on Sunday August 20, 2017 @05:20PM (#15060304)
IDEs promise a lot, and in many cases they deliver at least some of them. But they're all or nothing: to benefit, you must use their text editor, their debugger, their supported suite of compilers, their documentation browser, their everything.

A trend has emerged recently: editor-agnostic language oracles. These tools expose an IPC interface for querying, and in some cases even mutating (i.e. refactoring), source code. They often incorporate a compiler so the type information you get is perfect, and exactly what the compiler sees. Integration with the programmable text editor of your choice (vim, Emacs, Atom, Sublime Text, VSCode…) is a simpler matter of making the right IPC calls.

I think this is the sweet spot. I would hate to be locked into an IDE's poor text editor or buggy interface just because they offer some convenient tools.

Some examples of editor-agnostic tooling:

* CIDER for Clojure and ClojureScript (via weasel or figwheel). The primary editor plugin is Emacs, but vim and Sublime Tex support exists outside the main repository.

* rtags and ycmd for C and C++

* tern for Javascript

* racer and RLS for Rust

* eclipse.jdt.ls for Java

* guru for Go

Microsoft has even created a protocol for these daemons to follow, which makes editor integration even simpler: https://github.com/Microsoft/language-server-protocol/wiki/P...

Re:What is Hindley-Milner and why is it cool? (2008) by Groxx on Monday August 21, 2017 @02:55PM (#15066769)
Oh yeah, very much agreed (though debuggers are rarely bound so tightly in my experience). And all the language-server-protocol stuff seems exciting and fantastic and I hope it brings about a new breed of tools

But that's probably still a year or two away at least for any given language for basic support, much less reaching parity with mature IDEs. In the meantime...

Re:What is Hindley-Milner and why is it cool? (2008) by DonaldFisk on Sunday August 20, 2017 @04:13PM (#15060046)
The editor I had to write for Full Metal Jacket (my visual dataflow language) infers types by a mechanism similar to Prolog unification when you draw edges to connect vertices/function calls, and won't let you draw edges where the types at each end are incompatible. I imagine it would be a lot harder to do this in an editor for a text-based language, so it would probably be left to the compiler to check, which would have to build its own graph connecting function calls.

Incidentally, things have moved on in the functional programming world from vanilla Hindley-Milner types, and there's a lot of interest now in dependent types, which depend on values returned at run time, e.g. if you're drawing on a window, the x-coordinate's type is a number from 0 to the window's width, which might change while the program is running. This adds an extra layer of type safety, eliminates a further class of errors, and allows the compiler to safely remove some run-time checks.

Re:What is Hindley-Milner and why is it cool? (2008) by vilhelm_s on Sunday August 20, 2017 @06:25PM (#15060550)
For emacs and ocaml, caml-types.el is simple but very helpful. (It reads the type information generated by the ocaml compiler's -annot option.)

http://caml.inria.fr/svn/ocaml/trunk/emacs/caml-types.el

Re:What is Hindley-Milner and why is it cool? (2008) by yaantc on Sunday August 20, 2017 @04:12PM (#15060038)
Merlin [1] can provide type information for OCaml and integrates with emacs, vim and sublime (at least). One can easily select any expression and get its type. From experience, it's very convenient to spot mistakes leading to properly typed code, but not with the expected type(s).

[1] https://opam.ocaml.org/blog/merlin-2-0-0-released/

Re:What is Hindley-Milner and why is it cool? (2008) by lambdawitch on Sunday August 20, 2017 @03:08PM (#15059779)
I have this for both OCaml and Haskell in Visual Studio Code.
Re:What is Hindley-Milner and why is it cool? (2008) by throwaway613834 on Sunday August 20, 2017 @03:30PM (#15059874)
Visual Studio does that for Python. It occasionally fails (e.g. it doesn't have definitions for built-ins like map()) but overall it's pretty decent.

(It also does that for C++ and C# and whatnot for inferred types, but I thought I've seen other editors do it too...)

Re:What is Hindley-Milner and why is it cool? (2008) by sacheendra on Sunday August 20, 2017 @03:06PM (#15059763)
I don't know if it is available for other languages. But IntelliJ does it for Kotlin.