Having just read https://lexi-lambda.github.io/blog/2020/01/19/no-dynamic-type-systems-are-not-inherently-more-open/, I think you might find it to have some interesting ideas.
This blog post would benefit from having a broader set of languages it considers. For example, when you talk about strong vs. weak typing, there is also the extreme of a type system that lets the programmer completely break the type system. For example, in C you can get the address of a value and cast it to a void*, then you can cast that void* to whatever other type you want. Consider something like this.
int main(void) {
double x = 99.9;
void *vpx = &x;
int a = *((int*)vpx);
printf(“%d\n”, a);
}
This prints -1717986918 on my computer. You’ll probably get that on most computers since they are all running x86 processors, but if you went to an ARM chip the switch from little-endian to big-endian would change the output.
What really matters here though is that we just completely broke the type system. We converted a pointer to an 8-byte double-precision floating-point number to a 4-byte int and it let us. gcc didn’t even give a warning by default. This is truly weak typing, and it is enabled simply because you can cast a void* to any other pointer type in C. The C language doesn’t really have any proper mechanisms for expressing polymorphism. This casting of pointers is how the language allows you to write polymorphic code. The language doesn’t absolutely nothing though to check if what you did adheres to the proper types. This is MUCH weaker than languages like Perl that just have really liberal conversions between types. When you do “1abc”+1 in Perl and get 2 it is actually doing type conversions to get there. I would argue that isn’t even technically weak typing, it is just a very liberal set of implicit conversions. Truly weak typing doesn’t do nice type conversions. Here’s that example in C.
int main(void) {
char *str = “1abc”;
int sum = 1 + *((int*)((void*)str));
printf(“%d\n”, sum);
}
This prints out 1667391794.
Note that you can do this same stuff in C++. I had to add a const on the declaration of str to make g++ happy, but that was the only difference. Granted, C++ includes a lot of mechanisms to support polymorphism so you aren’t supposed to do silly things like this unless you have a reason you want to manipulating things at a very low-level in memory.
Including some functional languages could make the discussion more interesting as well. Statically-typed functional languages have some of the most powerful type systems.