Smarter Help: Our Programming Tools
In The End of Dynamic Languages, I argued that one of the gains of statically-typed languages is superior tooling.
Can the same be said for dynamic languages? It seems that the correct answer here is: it can improve.
I’ve been using rubocop and HoundCI. They are the wrong tools. For example, here are some of the errors Hound threw at me for a recent PR:





None of these are useful! They contribute nothing whatsoever to the quality of the code. It is candy for stylistic pedants—nothing more.
Well you can just disable those rules, you argue. Yes, you can, just
muck with this 1000+
lines of configuration so that you can create strings with
's instead of "s.
This is a false sense of quality and accomplishment.
The fact that it checks in your PR worsens the problem. We need systems to help us at the code writing stage, not before merging into master.
What we need
The closer we can get our tools to work with us instead of against us, the better we will be.
Below is an example how hlint helps me refactor as I write code. First, I write this function that adds up the values of the list:

But hlint finds a reduction:

And another:

Turns out sum already exists:

What we need are tools that, more and more, understand intent.
And because Haskell is statically typed, you can search for things
via the type. For example, if I need a function that flattens
[[a]] (a list of lists of as) into
[a], I can search for that on Hoogle ([[a]] -> [a])
and find the function concat :: [[a]] -> [a].
These tools today mirror the first batch of AI research: it’s mostly (if not all) symbolic reasoning.
Of course some work is being done outside of symbolic reasoning. We can use more than just types. Kite, for example, is interesting because clearly it’s parsing the code, but it also leverages and organizes the ocean of programming knowledge available online.
It’s clear that more we assist our tools, the more our tools can
assist us. Clojure’s spec can be a
huge win because it adds symbolic metadata that a program can read and
manipulate. Property-based testing (ala QuickCheck) also
works together with types to convey information that types cannot;
namely, the invariants (or property) of our functions.
But I don’t know how far you can take this without types. If you give
me an untyped AST, there is not much I can do, other than perhaps
memorize or regex for some known modules and their functions (aka
auto-complete). But it won’t be able to do what hlint can
do, because it can’t manipulate that untyped AST in a sure way.
Underlying all of this is a realization that the programmer
and the tools affect each other. If you experience, for
example, the power of property-based testing, you will begin to write
your programs in a property-testable way. If your type system guides you
to writing correct programs, then you will accept its assistant. If they
complain about you using ' instead of " for
strings, then, well, you should uninstall that tool.
The next generation of tools should combine symbolic, statistical and data mining techniques. We should take as much help as we can, from types and specifications and properties and data mining. The point is, we need help. And we need smarter help.