[Haskell-cafe] Type System vs Test Driven Development
Jesse Schalken
jesseschalken at gmail.com
Thu Jan 6 05:45:35 CET 2011
You need both. A good static type system will tell you whether or not the
code is type-correct. It will not tell you whether or not it does what it's
supposed to do.
Consider:
sort :: [a] -> [a]
If you change sort to be:
sort = id
It will still type check, but it obviously doesn't do what it's supposed to
do anymore. You need tests to verify that.
If you then change sort to be:
sort _ = 5
Now it's also type-incorrect. Static typing will catch it at compile
time (eg. Haskell will now infer the type as "Num b => a -> b" which will
not unify with "[a] -> [a]"), and dynamic typing will likely throw some sort
of type error at run time in the places it was previously used. (Any error
thrown by the language itself, like PHP's "Cannot call method on non-object"
or Python's "TypeError" or even Java's "NullPointerException" or C++'s
"Segmentation Fault" can be considered a type error.)
So with static typing, the machine will verify type-correctness, but you
still need tests to verify the program meets its specification. With dynamic
typing, you need tests to verify that the program meets both its
specification *and* doesn't throw any type errors - so you need to test
more.
The fact that most errors in programming are type errors and that Haskell
programs therefore tend to "just work" once you can get them past the type
checker may lead you to believe you don't need to test at all. But you still
do for the reasons above, you just need to test a hell of a lot less.
On Wed, Jan 5, 2011 at 8:44 PM, Jonathan Geddes
<geddes.jonathan at gmail.com>wrote:
> Cafe,
>
> In every language I program in, I try to be as disciplined as possible
> and use Test-Driven Development. That is, every language except
> Haskell.
>
> There are a few great benefits that come from having a comprehensive
> test suite with your application:
>
> 1. Refactoring is safer/easier
> 2. You have higher confidence in your code
> 3. You have a sort of 'beacon' to show where code breakage occurs
>
> Admittedly, I don't believe there is any magical benefit that comes
> from writing your tests before your code. But I find that when I don't
> write tests first, it is incredibly hard to go back and write them for
> 'completed' code.
>
> But as mentioned, I don't write unit tests in Haskell. Here's why not.
>
> When I write Haskell code, I write functions (and monadic actions)
> that are either a) so trivial that writing any kind of unit/property
> test seems silly, or are b) composed of other trivial functions using
> equally-trivial combinators.
>
> So, am I missing the benefits of TDD in my Haskell code?
>
> Is the refactoring I do in Haskell less safe? I don't think so. I
> would assert that there is no such thing as refactoring with the style
> of Haskell I described: the code is already super-factored, so any
> code reorganization would be better described as "recomposition." When
> "recomposing" a program, its incredibly rare for the type system to
> miss an introduced error, in my experience.
>
> Am I less confidence in my Haskell code? On the contrary. In general,
> I feel more confident in Haskell code WITHOUT unit tests than code in
> other languages WITH unit tests!
>
> Finally, am I missing the "error beacon" when things break? Again I
> feel like the type system has got me covered here. One of the things
> that immediately appealed to me about Haskell is that the strong type
> system gives the feeling of writing code against a solid test base.
>
> The irony is that the type system (specifically the IO monad) force
> you to structure code that would be very easy to test because logic
> code is generally separated from IO code.
>
> I explained these thoughts to a fellow programmer who is not familiar
> with Haskell and his response was essentially that any language that
> discourages you from writing unit tests is a very poor language. He
> (mis)quoted: "compilation [is] the weakest form of unit testing" [0].
> I vehemently disagreed, stating that invariants embedded in the type
> system are stronger than any other form of assuring correctness I know
> of.
>
> I know that much of my code could benefit from a property test or two
> on the more complex parts, but other than that I can't think that unit
> testing will improve my Haskell code/programming practice. Am I
> putting too much faith in the type system?
>
> [0]
> http://blog.jayfields.com/2008/02/static-typing-considered-harmful.html
>
> _______________________________________________
> Haskell-Cafe mailing list
> Haskell-Cafe at haskell.org
> http://www.haskell.org/mailman/listinfo/haskell-cafe
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/haskell-cafe/attachments/20110106/e8d28f1c/attachment.htm>
More information about the Haskell-Cafe
mailing list