Dynamically typed languages are not the same as weak typed languages. Dynamically-typed languages, like Ruby, still have data types like String, Float, etc. I've seen people use floats in statically typed languages before and end up with rounding errors simply because they chose Float instead of Decimal.
I am fully aware of the differences between weak typing and dynamic languages.
The issue I have with dynamic languages with types is that the type is usually inferred based on the operation. It's very easy to make mistakes and for those mistakes not to be apparent until the shit hits the fan.
Fully statically typed languages put these concerns right in your face and make you think about them.
> Fully statically typed languages put these concerns right in your face and make you think about them.
That depends slightly - if your compiler uses Damas-Milner type inference, it's possible that the compiler will assign the most general type signature possible to your function, which will not prevent this type of error, as operations such as addition work on either integral or floating point numbers.
What you're really after is a strongly typed language that also has explicit type declarations (or a programmer that's reliable enough always to include them even when they are optional).
One counter example is Java and Python. In Java this is allowed and the result requires knowledge of detailed rules:
int i = 10;
int j = 20;
String s = "Test " + i + j;
In Python the equivalent is an error.
The 'in your face' difference between a statically typed language and dynamic one is the time difference between the compilation error and an execution error. One tool for working effectively with dynamically typed languages is to keep that time difference short with tools like unit tests.