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 <[email protected]>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 > [email protected] > http://www.haskell.org/mailman/listinfo/haskell-cafe >
_______________________________________________ Haskell-Cafe mailing list [email protected] http://www.haskell.org/mailman/listinfo/haskell-cafe
