

Static Typing is not enough - jdeseno
http://blog.fogus.me/2012/06/20/not-enough/

======
tikhonj
Yes, static typing is not enough. Which is why a good statically typed
language like Haskell also has great testing facilities. So you don't just
write well typed code, but you also write unit tests (HUnit) and property-
based tests (QuickCheck). The really neat bit is that static typing actually
makes writing tests easier--QuickCheck is much easier to use in Haskell than
it would be in some dynamically typed language.

~~~
Dn_Ab
QuickCheck is great and can be found in many languages - dynamic and static
alike - nowadays. Another tool that is currently unique to Haskell and is
easier to write tests for is Lazy/SmallCheck. SmallCheck shines in the left
long tail of failure. Its core idea is based on a powerful principle: _"If a
program does not fail in any simple case, it hardly ever fails in any case."_
[]

So SmallCheck works exhaustively to find a minimal counterexample within some
depth bound. This makes sense - when trying to characterize a structure for
failure (or anything) you can rarely do better than the simplest explanation.
However, when the problem lies in larger examples SmallCheck fails where
QuickCheck catches a result so something like Type Check -> SmallCheck ->
QuickCheck -> probably ok.

[] <http://www.cs.york.ac.uk/fp/smallcheck/> documentation

~~~
gtani
and the guarantees (both random and exhaustive testing) for GenCheck

[http://permalink.gmane.org/gmane.comp.lang.haskell.general/1...](http://permalink.gmane.org/gmane.comp.lang.haskell.general/19371)

------
nightski
Doesn't anyone view static typing as done in a language like Haskell as a form
of documentation? I am not saying ALL Haskell code can be deciphered by its
types - hell no. But a useful technique is to express the semantics of the
program into the type system (as much as possible anyways) to communicate
intent. This is a huge benefit over dynamic languages imho. So there is more
too it than just verification, even if that is extremely nice.

~~~
tikhonj
This is actually a rather underrated property of good static type systems.
Some types (like (a, b) -> a or a -> b -> a) are actually so constraining,
they can only have one valid (e.g. not ⊥) implementation. There is actually a
program that, given a type signature, can write the trivial function for you
[1]. It's pretty awesome, but admittedly more a curio than anything practical.

[1]: <http://lambda-the-ultimate.org/node/1178>

Happily, there are practical programs that take advantage of the types'
expressiveness. My favorite example: Hoogle[2]. It's brilliant: a search
engine that given a type signature gives you a list of functions either with
that type (modulo renaming) or a similar type. The beauty is that it can work
even if the function is more general than what you're looking for and has a
weird name (so a normal search would not be very helpful).

[2]: <http://www.haskell.org/hoogle/>

A perfect example: let's say you're looking for the equivalent of JavaScript's
join method. It would have the type [String] -> String -> String. Now, this
particular function does not actually exist in Haskell. Instead, there is a
more general function called intercalate that works on any list. Moreover,
intercalate's arguments are reversed: it's type is actually [a] -> [[a]] ->
[a] (or String -> [String] -> String if made specific to String). And yet, if
you search for [String] -> String -> String, the second result is intercalate!
It's magical.

In short: types are basically a form of self-documenting code, so you get a
lot of cool stuff for free given a good type system.

------
chipsy
This is as much a usability problem as it is a "getting it right" one. We
could eventually "get it right" by plugging in raw machine code through
switches or punchcards if that's really what it took, but what we're arguing
over is the _price_ of getting it right.

Static types are implemented and available for use at the language level,
which isn't true of all of those features in most environments.

------
carsongross
Neither static typing (nor any of the other stuff mentioned) is enough to
ensure correctness. Never has been, never will be.

However, static typing _is_ enough for some sweet, sweet hit-dot-wtf-can-i-do-
completion-refactoring-like-a-boss tooling goodness.

~~~
fogus

        (any of the other stuff mentioned) .. ensure correctness
    

The post says that.

Dot-completion in your IDE is not enough either, nor is it something
particularly unique to static languages.

~~~
carsongross
Reliable dot completion without some batshit insane state-dependent VM-as-a-
dev-env-or-constantly-running-tests system is... well, let's just say made
much _easier_ with static typing.

I really could give a shit about what people think is "enough" (IMO, keeping
stuff simple, as in simplicity of implementation, as in worse-is-better, is
the only answer) I just want to hit dot and have a pretty good idea what I'm
allowed to do. And static typing, in practice, appears to help there.

But hey, man, I'm not advocating _you_ use it.

~~~
jshen
Pry for ruby gives me great dot completion and isn't batshit insane. Most
diehard dynamic typists live in their repl. When I use java with IntelliJ I
miss my repl. I do gain some things from the IDE, but I feel hamstrung
compared to my repl.

~~~
carsongross
Ah, f __k man, another REPL?

I don't _want_ a repl for editing. I _want_ to write code in a friggen editor
and have dot completion work.

I _also_ want a repl for trying stuff out and debugging/light weight testing,
but that's a different use case for me.

~~~
jshen
<https://github.com/pry/pry/wiki/Editor-integration>

~~~
ehsanu1
But that doesn't give you autocomplete within the editor, it seems like it
just opens up the editor and evals the file after exiting the editor.

~~~
jshen
Technically true, but I write most of my code in the REPL, then use edit-
method to get it into my editor.

Fom the link: NOTE: If you're using Ruby 1.9, you can use edit-method on
methods defined from the Pry console. As these methods have no associated
file, this implies the -p switch. This functionality doesn't yet work for Ruby
1.8.

------
cageface
Yep, there is no silver bullet.

But that doesn't mean all bullets are created equal.

~~~
marknutter
Yes, but perhaps we it means we can stop bitching about each other's bullets
of choice and get back to shooting.

~~~
tikhonj
That would be great if I could just work by myself, happily use Haskell and
not worry about bosses mandating something really annoying like Python or
Java. In fact, that's one of the main reasons I'm working at a tiny startup
right now. But I digress; my main point is simple: since chances are your
choice of bullet affects others' choices, especially in corporate settings, it
would be much better if it were a good choice.

~~~
marknutter
And "good choice" remains subjective. Round and round we go. Somebody stop
this thing before I puke.

~~~
tikhonj
Well yes. But my point is not that you should use technology X but that just
letting you "get back to shooting" could very well be detrimental. In this
particular point I'm not defending any particular technology but rather having
discussions and disagreements about technologies. After all, you do not
program in a vacuum.

------
ternaryoperator
Kind of a strawman argument, as no developer would argue that _only_ unit
tests and static typing are needed to guarantee quality.

~~~
lmm
It's a response to a previous article, which really did make the argument
"unit testing does not guarantee quality, therefore you need static typing".
So not a strawman.

~~~
skew
The previous article really didn't make the argument "all you need is static
typing". It was specifically refuting the idea that "all you need is unit
testing" - or at least that unit testing is a complete replacement for static
types.

The paper makes a point of reporting that most unit tests could not be
replaced by static types.

What of that looks like a claim that you only need types?

~~~
ajanuary
The previous article said "unit testing isn't enough, you need static types
/as well/". This article is extending that argument to "unit testing and
static types aren't enough, you need xyz /as well/".

I believe the point is that there will always be something your current test
strategy doesn't cover. At what point do you draw the line?

If unit tests and static types don't cover everything, what says that's
enough? And can the justification for that, whatever it is, be applied to
"unit tests are enough" also?

------
modarts
Yet another attempt to diminish the value of statically typed languages and
the benefits that go along with them.

~~~
fogus
I'm question if you read the post because I didn't diminish anything. I did
say that it is a tool in the fight of software validation however.

~~~
jdeseno
It seems to be a trend; gloss over the article then infer most of the meaning
from the title.

The title I submitted isn't great but, I can't seem to correct it.

------
gbog
In a conference 15 years ago I heard a guy say The problem with software is we
don't know what it is. He meant that: we know what is a car or a bridge, we
know why and how they do their purpose, not so much with software, which is a
strange beast our minds are not ready to grab yet.

~~~
morsch
There might be something to that. But maybe some construction and automobile
engineers feel the same way about bridges and cars respectively. God, I hope
not. :)

------
qznc
You need formal machine-checked verification (Coq, Isabelle).

Unfortunately, this is not enough. You need a consistent and complete
specification, too.

~~~
skew
The first half is a bit easier - if you can show some implementation meets the
specification it is at least consistent.

The second isn't so clear, but sometimes you can get a bit more confidence by
showing that other good properties are implied by the specification alone.

------
buster
Doesn't matter because, what really matters is Think-before-you-code, all that
static typing will save noone from bugs.

Also: <3 Love Driven Development <3

------
cpfohl
I'm really curious what Love Driven Development would look like. Is it kind of
like TDD in that before you write a single line of code you write a sonnet
about it?

------
tomp
Sometimes, I wish I could downvote stories...

Accidentially, almost everything that the author suggests, except luck and
user testing, can be provided by static type systems - e.g. Haskell's type
system is Turing-complete, so you can make up any kind of contracts/tests and
embed them into the type system...

~~~
jerf
With appropriate compiler flags, you can make up any sort of contracts you
like in Haskell. But there's no guarantee that the compilation process will
terminate if you do, even putting aside the impenetrability of the resulting
code. Haskell is not a general purpose proof assistant, and the typing
definitely has limits both practical and theoretical. Abstractly, static types
can represent anything, however we (by which I mean humanity in general)
certainly do not know how to use such powerful types in real, general purpose
code.

If you want to go that road, look up Agda or Coq.

~~~
prodigal_erik
Why do people worry about compilers hanging or giving up? If I know how to
kill the failed compile and fix _my_ program so that it is provably type-safe
before shipping, I don't really care how many undecidable programs could also
exist because I no longer have to ship one of those.

~~~
jerf
Because if the compiler hangs, you don't get any executable code. And in the
specific case of Haskell, we are talking about type constraints that are
perfectly cromulent, are perfectly correctly expressed and mean something in
some abstract mathematical world in which your have infinite compiler time,
but in the real world will simply never finish compiling. It's not because
you've failed and you can fix it by twiddling something, it's because Haskell
is not actually that sort of language, and if you try to actually use the type
system as a Turing-complete constraints satisfaction language, you'll get
exponential performance... or _doubly_ -exponential performance, or worse,
though it stops mattering pretty quickly.

In both theory and practice, this means you can't really use Haskell that way.
It's a typed language with the ability to occasionally skirt the limits, ride
the line, and dip into a bit of undecidability when useful (and with a real,
in-practice risk of it blowing up in your face even so), not a language in
which one routinely uses the type system in a "Turing complete manner", if I
may be allowed to gloss over precisely what that means. Richer type systems is
a topic of ongoing research, but is not a solved problem.

~~~
prodigal_erik
So the problem is that there are too many useful programs which can't be
expressed in a practically decidable form, or there's no clear way to get from
a form that isn't to a similar-enough form that would be, like knowing what
strategies ghc uses to narrow the search space or something?

------
chj
Big take away: Love Driven Development Rules Them All.

------
saraid216
LDD ftw.

