Earlier quoted context omitted.
I don’t get the cost claims. The time it takes to note which type I intend something to be is mostly either so low that I recover it via improved hints and such very quickly, or larger but only because I’m documenting something complex enough that I should have documented it anyway, whether or not I was using static types, because it’ll be hell for other people or future-me to figure out otherwise. It seems like a la…
I think the general feeling is that there are some code patterns that are safe and easy to do with dynamic typing, but impossible with simple type systems or more complex with more advanced type system. An example would be Common Lisp's `map` function [0] (it takes a number of sequences and a function that has as many parameters as there are sequences). It would be hard to come up with a type for this in Java, and it…
There are better languages for expressing this more natural (such as Idris) but in the end, the fallacy seems to lie in your claim that this would be "safe and easy to do with dynamic typing". That's what you think until you find out that your solution works in 99% of the cases, except in some special cases, because the compiler didn't have your back.
Examples are the standard sort functions in Java and python, which were bugged for a very long time.
Btw, here is the executable code in Scala: https://scalafiddle.io/sf/UrDu12b/1
Posting it for reference in case Scalafiddle is down:
import shapeless._, ops.function._
def multiMap[InputTypes MapResult]) = inputs.map(fn(mapF))
val testList2Elems = List(
3 :: "hi" :: HNil,
5 :: "yes" :: HNil
)
multiMap(testList2Elems){ (num: Int, str: String) =>
s"$num times $str is ${List.fill(num)(str).mkString}"
}.foreach(println)
val testList3Elems = List(
3 :: "hi" :: 3 :: HNil,
5 :: "yes" :: 2 :: HNil,
2 :: "easy" :: 1 :: HNil
)
multiMap(testList3Elems){ (num: Int, str: String, mult: Int) =>
s"$num * $mult times $str is ${List.fill(num*mult)(str).mkString}"
}.foreach(println)
// As expected, the compiler has our back and the following does not compile
val testListWrongElems = List(
3 :: "hi" :: HNil,
5 :: "yes" :: "ups?" :: HNil
)
/*
* Whoops, does not compile, list shape not good for multiMap :)
*
multiMap(testListWrongElems){ (num: Int, str: String) =>
s"$num times $str is ${List.fill(num)(str).mkString}"
}.foreach(println)
*/
/*
* Whoops, does not compile, 2-sequences vs 3 argument function :)
*
multiMap(testList2Elems){ (num: Int, str: String, mult: Int) =>
s"$num * $mult times $str is ${List.fill(num*mult)(str).mkString}"
}.foreach(println)
*/