That's not true. The compiler will give the function the most general type it can infer, which in this case is
holds :: Eq a => UnionFindElement a -> a -> Bool
The point of the article is sound - using the interpreter to ask for types is a great way to work (and often leads to surprising realizations which can lead you to generalize and abstract your code), but the reasoning is spurious. Most of the time, you don't need to supply types in Haskell, as the compiler is perfectly capable of figuring them out for itself.
I love type inference, but I feel like using it in this way doesn't realize its full potential. My functional background primarily stems from SML (and some Clojure), but the logic I'll use should apply here as well. It's true that the compiler is able to infer the most general type itself, but if you rely on it for this you're ignoring an invaluable tool for predicting the correctness of your code.
There are many times where I've used type inference to show me there's an issue with my code before I even run a single unit-test. I always specify the types of my arguments as well as the return type when writing a function, even though it's not technically required at this point. If I've fully reasoned through what it needs to do then this shouldn't be too difficult. Once I've finished I'll make sure it type-checks. If it does then I'll know the logic throughout my function matches the inputs and outputs I've specified.
That gives you a powerful low-pass filter for knowing whether or not your code is more likely to be correct. If you specify the types when you declare the function and they don't match then your code won't type-check, which results in an exception. If you don't, then depending on the type of error your function might still type-check and compile, but with the wrong type. Then you have no choice but to catch the error with unit tests or, even worse, debugging. The interpreter will certainly give you the type for the code that you've entered, but assuming that it's giving you the type for the code you actually need leaves a powerful tool on the table.
Obviously this doesn't cover every class of error you could have in your code of course, but it in my experience it can be very helpful.
1. Write the function and the type together, and use the type checker to perform an initial check for program correctness.
2. Write the function and the type, but comment out the type, and see if the type checker can infer something more general than the type you supplied.
3. Write the type but leave the function undefined - this gives you a skeleton of your project and lets you write both top-down and bottom-up at the same time, filling in the details later on.
4. Use a function, but leave it undefined and don't give it a type. The type checker can infer a type for it, which often helps you write the function itself.
5. Write the functions but not the type, and let the type checker figure the whole thing out (great for throwaway programs and scripting).
With combinations of these, and a brutal dedication to refactoring and modularisation, I find that I can quickly develop correct, re-usable code.
I have been confused by the fact that I got errors while I was not constraining the type in the right way.
You should then examine the result and make sure it is correct. In this case, you wrote the type signature incorrectly on an otherwise-correct function, but you will also frequently find that what you wrote is syntactically valid but has a type you did not intend at all, because it is actually wrong. For instance, it's easy to end up missing a parameter passing somewhere and ending up with an unexpected function showing up in the inferred signature.
You can also find that the GHCi-inferred type signature is correct, but not what you particularly wanted. Sometimes you may want to deliberately constrain it to something tighter than it will infer. And the other major case I've seen is that you may want to write the type signature with synonyms you've created; if you fix the type signature with those, GHCi will use them in the future if you ask for the type.
Also, there's djinn
("cabal install djinn" works to install it.)