
On Thu, 2006-01-26 at 19:35 +0000, Olaf Chitil wrote:
As response to both Aaron and Duncan,
foo 0 = ... foo n = ...
And what about the negative numbers? For negative numbers the second equation matches, which in 90% of all cases in practise has never been written for them. Aaron's Ackerman function disappears in infinite recursion... Besides, what is ack 0.5 0.5?
Isn't the same true for: foo n | n == 0 = ... | otherwise = ... It's still going to fail for negative numbers.
The use of n+k patterns, but also the definition pattern above wrongly lead programmers to believe that they are dealing with natural numbers. There is no nice primitive recursion for integers. Even worse, without a type signature restricting its type, foo will be defined for all numeric types. For Float or Rational it makes hardly any sense.
The above example is still defined for all numeric types. Eliminating that syntax form doesn't remove those problems.
If Haskell had a type for natural numbers I'd be in favour of n+k and k patterns (working only for this type, not any other numerical type).
I'm in favour of removing n+k patterns too.
Using primitive recursion on integers or even arbitrary numbers is misleading. You can teach primitive recursion nicely for algebraic data types, because the recursive pattern of the function definition follows the recursive pattern of the type definition.
Char is a type that is not constructed recursively and yet no one seems to have problems with character literals as constructors and thus as patterns. Each character literal is a Char constructor. Why can't each numeric literal be a constructor for the numeric types? I think it's a perfectly reasonable mental model for people to believe that: data Char = 'a' | 'b' | 'c' | ... data Int = ... -2 | -1 | 0 | 1 | 2 | ... I don't see why we should remove one and not the other. Students will ask why the can pattern match on strings, characters and booleans but not numbers. Perhaps primitive recursion on integers is misleading, but people will still write foo n | n == 0 = ... | otherwise = ... where they previously wrote foo 0 = ... foo n = ... so what have we gained except less notational convenience? Not all pattern matching on numeric literals is involved with recursion on integers, where as virtually all n+k patterns is used for that purpose. So there is some distinction between the two forms. n+k patterns are a quirk of the numeric types. k patterns are regular with other types in the language.
With respect to tools of which Hat is one example: If it is hard to build tools, then less tools will be built. Compare the number of tools for Scheme with those for Haskell. Most tools grow out of student projects or research projects; these have rather limited resources.
It's partly the complexity of the language and partly because our latest language spec (H98) is not the language that we all use (H98 + various extensions). I'm sure Haskell-prime will help in this area. I don't mean to belittle the difficulty of building tools. I know how hard it is, I'm trying to build one too. Duncan