TL/DR:
Success typing considers all possible types a value can have. If a function returns either a bool or an int and you then pass that value into a function that accepts a string or an int, then the success typing checks out. It doesn't mean your program is correct, but that it could possibly be correct. On the other hand, if you pass the "bool or int" value into a function that only accepts a string, the type checker will complain and you know for sure your program is incorrect. In other words, you will get false negatives but never a false positive.
Perhaps more relevantly, in a dynamic, duck-typed language in which methods can be overridden per-object, there is no guarantee that an instance of class String actually implements any given contract (including that implemented by unmodified instances of class String).
So, contracts that specify what functions accept and produce by class membership provide less assurance than they superficially appear to.
Ruby is not a duck-typed language. "duck-typing" is only touted by its community to award it free credibility and merit where there is none. "duck-typing" is essentially free for any dynamic typed language which have method RTTI. So please, stop the "duck-typing" pride parade. It is nauseating.
Huh? If Ruby is not duck-typed, can you give me an example of a something that is? It seems like the textbook example. Here are two weird examples:
1. C++ templates and
2) C# variables declared dynamic (I don't know C#, could be wrong)
Are we using the same definitions as each other?
Duck typing is more of a technique than a quality of a language. Any dynamically-typed language is going to end up having some code that does runtime type checking. Duck typing just means doing respond_to? instead of :kind_of? when doing so.
Ruby is certainly a language suitable for the duck typing technique. The term was originally used in reference to Python, and both languages have reasonably equivalent reflection abilities.
http://user.it.uu.se/~kostis/Papers/succ_types.pdf
TL/DR: Success typing considers all possible types a value can have. If a function returns either a bool or an int and you then pass that value into a function that accepts a string or an int, then the success typing checks out. It doesn't mean your program is correct, but that it could possibly be correct. On the other hand, if you pass the "bool or int" value into a function that only accepts a string, the type checker will complain and you know for sure your program is incorrect. In other words, you will get false negatives but never a false positive.