The source content for blog.juliobiason.me
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2.7 KiB

+++ title = "The Problem With Gradual Typing Examples" date = 2023-07-12 draft = true

[taxonomies] tags = ["programming languages", "typing", "static typing", "progressive typing"] +++

Gradual Typing offers the mixed results of static typing and dynamic typing: You can let the compiler/interpreter fight with the types in the runtime when you don't specify them, but you can say the type of a variable and the compiler/interpreter will pick incompatible type operations before it runs.

But the examples I've seen always pull things in, in my option, the wrong way.

The general example of a bad thing for gradual typing is this type of code:

def add(a, b):
    return a + b

The issue is that there are multiple values that can be added. If we consider just the primitive types of Python, we would get something like:

from typing import Union

CanAdd = Union[str, float, int]

def add(a: CanAdd, b: CanAdd) -> CanAdd:
    return a + b

This code obviously breaks on other things can be added. For example, you can create an class, override its add/+ operator and, thus, objects of said class can be added. But because our just-primitives types doesn't list our new class, the compiler/interpreter would never accept a call of add() with those objects.

(There is another issue, sometimes cited, sometimes don't, about the fact that there is nothing saying that the type of b must be the same type of a and thus one could add an integer to a string, which is... wrong.)

But I have a question:

Is that a real world kind of function?

Oh, don't get me wrong: Simpler functions, with just as few lines is quite normal. Something that would be real1 would be something like:

def item_total(qty: int, price: float) -> float:
    return qty * price

I guess this is more common than add(), because it is an operation that happens most of the time. And this would get the case of

def receive_api_request(json_data):
    ...
    for item in json_data['items']:
        total += item_total(item['price'], item['qty'])

If you don't type check, this would produce exactly the same results. But the code is wrong, and if someone do a small change in item_total(), you'd end up with a strange thing in which only this call produces the wrong results, while all other interfaces would (probably) produce the correct result.

{% note() %} Surely there are issues, nonetheless. Python, which I used in this example, would still not accept anything that could be automatically coerced to int, even if such interface doesn't exist, although they are working on support types with "protocols". {% end %}



  1. For different values of "real".