A way to distinguish "gradual typing" from "anything possible"
Since the renaming any into untyped there is no good way semantically to separate your progress of gradual typing from the uncontrollable type.
In Datadog we build some tools to help us track gradual typing progress and we have to define our way to express situations like "this is user input and literally anything could be given".
For now, we just stick with a simplest solution to alias untyped as any and make an agreement to use any only when we can't narrow down the expected type due to its nature.
module Datadog
type any = untyped
end
Maybe we also could use some other types for that alias like Object or BasicObject, but this is not the point.
What is your opinion on RBS providing a built-in way to distinguish "I don't have to type it now" from "I don't control the type, it could be anything" or is there a better way of doing that differentiation?
It looks like you're looking for top, the super type of all types?
Here's how we use it with Sorbet:
# typed: true
#: (top) -> void
def foo(x)
x.to_s # error: Method `to_s` does not exist on `top`
end
foo(42)
foo(nil)
foo(->() {})
#: (untyped) -> void
def bar(x)
x.to_s # ok
end
bar(42)
bar(nil)
bar(->() {})
While top accept any type as input (all types are subtypes of top), it doesn't define any method.
"I don't control the type, it could be anything"
untyped
"I don't have to type it now"
__todo__ from #1520 ᗡ:
P.S.
Although I think every RBS prototyper spits out untyped, rather than __todo__, which suits gradual typing better?
Not just prototypers, steep stats reports untyped vs typed, as if untyped was more like __todo__.
@ParadoxV5 that __todo__ is interesting, but has a few issues:
- generators currently use
untypedas "I don't know, I couldn't figure it out, you should look at this" i.e what would be__todo__ -
steep statsshows progress of progressive typing as "typed calls" vs "untyped calls" (i.e "these method calls happen on untyped objects, PTAL"), revealing behind-the-scenesuntyped.
So let's imagine, it could be made that:
- generators generate
__todo__instead ofuntyped - tooling such as
steep statscount__todo__instead ofuntyped
But then what of the swaths of code that have already been generated as untyped by previous tooling? Suddenly the shift in semantics would make them all invisible.
I would argue then that introducing a any (by this name or another) that means "not todo, I really mean it" and keeping untyped as the "TODO" one could be the safe, non-breaking move.
Aliasing top (union of all types) as any is actually a good idea; there is even all for its opposite, bot (intersection, i.e., subtype of all types), for enabling contravariance.
I had some issues using top as a replacement for untyped in some specific case (sorry, don't have it at hand). But the idea is purely semantical with a minimum changes to the existing flow.
To keep untyped as a gradually reducing definition and any (implementation doesn't matter) as "I mean it's anything, I don't control it" definition.