
The Ergonomics of Type Checking (2016) - adamnemecek
https://michaelfeathers.silvrback.com/the-ergonomics-of-type-checking
======
adrianratnapala
_The type checker has questions, and it is adamant about them, refusing to let
you move forward until they are answered. Often, I’m ok with that. They are
good questions, and most of the time they really should be answered. The
question is: when?_

This is a good point. The poster then proposes being able to nail down your
types progressively -- which I think is fine as a long as you don't let the
iteration cycle get too long.

Optionally typed languages are one way we approach this ideal. Another way is
linters that are stricter than the compiler itself. You must run the compiler
to have testable code, but you can run the linter later, perhaps only as part
of CI.

It is possible that in future, both of these approaches will look like
primitive exteremes of some richer process progressively nailing down the
static safety of a program.

------
neilparikh
Haskell has a flag called -fdefer-type-errors
([https://downloads.haskell.org/~ghc/7.6.1/docs/html/users_gui...](https://downloads.haskell.org/~ghc/7.6.1/docs/html/users_guide/defer-
type-errors.html)) that gets you pretty close to the experience of ignoring
errors you don't care about right now.

~~~
twic
You can do something similar with Eclipse's compiler for Java, JDT, which
features [1]:

 _An incremental Java compiler. Implemented as an Eclipse builder, it is based
on technology evolved from VisualAge for Java compiler. In particular, it
allows to run and debug code which still contains unresolved errors._

That means that you can write something like:

    
    
        private void describe(String string) {
            if (string.isEmpty()) empty();
            else nonempty(string);
        }
        
        private void empty() {
            System.out.println("empty");
        }
        
        private void nonempty(String string) {
            System.out.println("contains " + string.size() + " characters");
        }
    
    

Then you can still run the code and call describe, but if execution reaches
nonempty, you get a runtime error telling you about the compilation problem.

It's one of the few things from Eclipse i miss when using IntelliJ.

[1] [http://www.eclipse.org/jdt/core/](http://www.eclipse.org/jdt/core/)

~~~
exceptione
I can't see a problem with nonempty, am I stupid?

~~~
Thiez
A `String` in Java has a `.length()`, not a `.size()`.

------
tedmiston
> I often wish I worked in a language where I could start dynamic and end
> statically... I can imagine writing the core of an algorithm and then
> gradually tightening the conditions as it comes into focus. More than a
> tool, this would be a practice: progressive type elaboration.

Bingo. I love this idea. I haven't tried it yet myself, but I think mypy [1]
from Dropbox makes this a reality today in the Python world.

[1]: [http://mypy-lang.org/](http://mypy-lang.org/)

~~~
sitkack
Came here to mention MyPy and optional typing, the preferable term Gradual
Typing means something distinctly different.

[http://mypy-lang.org/about.html](http://mypy-lang.org/about.html)

Dropbox employs the creator of MyPy but it isn't a creation of dropbox.

Type Systems as Macros [http://www.ccs.neu.edu/home/stchang/pubs/ckg-
popl2017.pdf](http://www.ccs.neu.edu/home/stchang/pubs/ckg-popl2017.pdf)

Pluggable Type Systems
[http://bracha.org/pluggableTypesPosition.pdf](http://bracha.org/pluggableTypesPosition.pdf)

Propositions as Types
[http://homepages.inf.ed.ac.uk/wadler/papers/propositions-
as-...](http://homepages.inf.ed.ac.uk/wadler/papers/propositions-as-
types/propositions-as-types.pdf)

[https://www.youtube.com/watch?v=IOiZatlZtGU](https://www.youtube.com/watch?v=IOiZatlZtGU)

~~~
tedmiston
> Came here to mention MyPy and optional typing, the preferable term Gradual
> Typing means something distinctly different.

Are you sure that gradual typing is different than what Mypy supports?

The Wikipedia page for gradual typing cites mypy as an example.

[https://en.wikipedia.org/wiki/Gradual_typing](https://en.wikipedia.org/wiki/Gradual_typing)

The Mypy docstrings specifically state:

> Mypy has a powerful type system with features such as type inference,
> gradual typing, generics and union types.

[https://github.com/python/mypy/blob/272d0c4c50918a36b57e7c0c...](https://github.com/python/mypy/blob/272d0c4c50918a36b57e7c0cc85c8cc6306ca72c/setup.py#L34)

The section on gradual typing in PEP 483 seems consistent with this as well.

[https://www.python.org/dev/peps/pep-0483/#summary-of-
gradual...](https://www.python.org/dev/peps/pep-0483/#summary-of-gradual-
typing)

~~~
sitkack
Do they really insert extra dynamic checks?

Is Sound Gradual Typing Dead?
[https://news.ycombinator.com/item?id=11041272](https://news.ycombinator.com/item?id=11041272)

[http://prl.ccs.neu.edu/gtp/research.html](http://prl.ccs.neu.edu/gtp/research.html)

It was my understanding that MyPy was purely compile time with no runtime
checks. But I could be wrong. Gradual Typing as implemented in the original
paper would lead to much much slower code. The weight of a static language
bolted onto a dynamic runtime for the worst of both possible worlds.
Sufficiently abstract Python code is almost un-typable.

I think eventually we will get there, where one can explore a program in a
dynamic language and ship a correctly statically typed one. Types are only the
beginning.

~~~
tedmiston
I believe you're right that Mypy only offers compile time type checking, but
not runtime.

It looks like there are some active projects for runtime type checking in
Python and while I don't believe Mypy is related to any of them, enforce [1]
looks to also use the same standard type hinting syntax from PEP 484.

[1]: [https://github.com/RussBaz/enforce](https://github.com/RussBaz/enforce)

------
zpr
Hate to be that guy but, Flow for JS is something like that. You can
optionally enable it and even enable/disable it in certain files, functions,
lines, etc.

~~~
hliyan
That is optional typing. The author is talking about gradual or progressive
typing.

~~~
zpr
But he mentions he wishes he could start dynamically and end statically. By
enabling Flow at the end, don't you basically achieve that? You can also
enable it progressively for files as you move on, and still rapidly prototype
without it. In fact, unless I'm mistaken I believe it's "opt-in" by default,
ie. Flow won't scan the file unless you include the special comment keyword at
the top of the file.

------
hliyan
Can't a compiler be created to traverse the AST, locate all operations
performed on the variable and infer the narrowest type definition that allows
for all of those operations, and then enforce at compile time?

Edit: example to further clarify what I meant (it's a bit more than type
inference at initial assignment)

    
    
        var x = readUserInput(); // narrow down: string, int, double
        x += y; // if y is also a user input, no change
        x += 1; // narrow down to int, double
        p = x % 2; // narrow down to int

~~~
bastawhiz
Many languages do this (type inference), to some extent. The moment you have
any expression that can evaluate to more than one type, though, it requires
annotations.

~~~
hliyan
Are there any languages that do it beyond the first value assignment, or
outside the current scope? Also, any languages that subsequently revise the
type definition?

~~~
tedmiston
Not sure if this is exactly what you're asking but one can reassign variables
to change their types in Python:

    
    
        >>> x = 1
        >>> type(x)
        <class 'int'>
        >>> x = 'foo'
        >>> type(x)
        <class 'str'>

~~~
xapata
I believe the question was about inferred static typing for union types.
Python does not do any static type inference.

Also, I'm not sure how a union type could be distinguished from an error
during type inference. Maybe a nullable, but otherwise it'd be very tricky.

------
nicoburns
As much as it gets a bad rep, I think PHP is actually the language that comes
closest to this. It's not quite there yet, as although newer versions of PHP
have been adding optional type annotations, they are enforced at runtime
rather than compile time. It seems not too much of a leap to imagine that some
compile time checks might be added at some point though once type-annotated
code becomes more universal.

------
jryan49
"Gradual typing" is one of the reasons I still love using Groovy :)

~~~
hliyan
I've recently come become aware of Groovy while looking for a programming
language with Java's features _without_ the need for object orientation. How
production ready is it? (I'm talking enterprise systems, not web based or
consumer applications)

~~~
jryan49
I really only use it as a glue code language or for automation. I thought that
at least a few years ago there were a bunch of people using Grails? After
using it extensively, I have found a few strange bugs that's killed some time
but nothing show stopping. For what it's worth, the bugs were at least in
their bug tracker. I would love to use it for everything but it seems to be
losing popularity, which is really the only reason that makes me hesitant to
do so. Maybe I should start contributing :)

~~~
etatoby
We still use Grails at work. Kill it. Kill it with fire.

------
viperscape
“I often wish I worked in a language where I could start dynamic and end
statically. There are a number of languages with optional type systems, but
they aren’t the ones that I use.“

That’s a shame because typescript is basically this. Typing is optional, and
you can become more granular as you want.

------
krylon
Now that it is finally there, I can say this without the usual jokes we have
grown so accustomed to:

Perl 6 does this.

Granted, (almost) nobody is using it, but it does exist (finally!).

~~~
hinkley
Right on time too!

Back in like 2006 they were estimating that all of the stuff they wanted to
put in 6 would require until 2016 or 2017 to complete. I figured that was a
comment meant to negotiate down the scope to something reasonable.

Turns out, no...

------
SolarNet
Julia does gradual typing very well. I think it delivers what the user wants.
It has a REPL, you can write code using no types, as types are added to
existing code it improves in performance and safety.

------
jingwen
If you're interested in learning more about gradual type systems, check out
Jeremy Siek's work [0, 1]. He's one of the early researchers in this area.

[0] [https://wphomes.soic.indiana.edu/jsiek/what-is-gradual-
typin...](https://wphomes.soic.indiana.edu/jsiek/what-is-gradual-typing/) [1]
[https://github.com/samth/gradual-typing-
bib](https://github.com/samth/gradual-typing-bib)

------
msl09
I think that type hints are becoming like that in the python world. Almost all
my code starts untyped and later I start adding types when they are not
trivial

------
z3t4
in JavaScript I pepper each function with if(...) throw, eg the program will
throw if something is wrong. Doing this catches a lot of errors and bad state.
- Without having to babysit a compiler (Typescript) and I can enjoy all the
dynamic features. Sometimes I miss the type annotation as documentation, but
then I just rename the variable to make it more clear what it is and does.

~~~
bitwalker
Instead of "babysitting" your compiler, you're "babysitting" your application
at runtime - I fail to see the difference.

~~~
z3t4
Good point. Think of it as hand-holding your peers instead of hand-holding the
compiler. if(x==y) throw "friendly error" // avoids eternal loop ... The
compiler doesn't care if you get an eternal loop at runtime, and static types
wont prevent it.

~~~
bitwalker
What prevents you from writing the exact same exceptional code in a static
system? I'm not sure I understand your point.

~~~
z3t4
If you make it a habit to write exceptions, it's more likely that you would.
Some people think tests etc is only needed because the language is dynamic.

------
mebassett
I can agree with the author's premise that types are essentially great, but it
would be useful to have control over when (if ever) in the development stage I
need to bring them, much like we do with testing. I guess there is an
underlying analogy between TDD and strong static typing. I think this is one
of the motivations for typed/racket, which is a lot of fun to use.

------
quickben
"I often wish I worked in a language where I could start dynamic and end
statically."

C++ 'auto' type. Workflow:

1\. Write 'auto =', see what the compiler picks up (iterator of a vector of a
set of classes that points to a list of structs, etc).

2\. Potentially copy/paste that (unless the line is bigger than 350 characters
:) )

~~~
jeremyjh
Type inference or deduction is not the same as dynamic typing. An auto
variable resolves to exactly one type, which is determined by the expression
it is bound to. If you pass that variable to a method expecting a different
type, the compiler will stop you. If it were dynamically typed, it would let
you proceed and fail at runtime.

------
iitalics
> I wish I had a language that did optional typing

> they exist, but I don't use them.

:/

The author's thoughts (I want to write dynamically to get the code working,
but then make it static afterwards) are nearly the exact thing I've heard from
Matthias Felleisen when he talks about the motivation behind Typed Racket.

------
emodendroket
The biggest value of static types is when you go to edit some code written
years and years ago and you can tell what the hell the intended usage was
without digging through the method

~~~
Guthur
Not even remotely universally true. I've seen plenty of static code that is as
obtuse as any dynamic code. Authorship holds far more sway than dynamic vs
static.

~~~
emodendroket
It is 100% less likely that you'll run into out-of-date docs wrongly
describing the types of the input arguments and return types. Of course the
code might still be obtuse but the type declarations are a form of
documentation that the compiler ensures is still up-to-date.

------
spullara
This is related to why all my companies use TypeScript rather than plain
JavaScript for their frontends and sometimes their backends (vs other
languages).

------
toolz
I imagine the author would appreciate the static analysis/success type
checking that erlang/elixirs dialyzer provides.

------
nearmuse
So PEP 484? You can write out whatever and then add annotations (at least to
the API).

~~~
pleasecalllater
So you spend time writing the things, which then are totally ignored by the
compiler/interpreter. Seems like a waste of time, except for documentation
purpose.

~~~
nearmuse
Those are actually enforceable by IDE or interpreter/compiler if implemented.
Even if this wasn't the case, it is better than some arbitrary variable naming
convention or comments format.

