
Types will be part of Ruby 3 stdlib source - darkdimius
https://twitter.com/darkdimius/status/1119115657776209920
======
_hardwaregeek
Very cool! I didn't think this would happen, as Matz has expressed disinterest
in adding type annotations. However, keeping an open mind and reconsidering
one's positions are the hallmarks of a great leader :D

I worked on a summer project to add type annotations to Ruby. Didn't get very
far since I ran into some challenges with the internals of the parser and the
parser library, Ripper. I'm extremely interested in seeing how the Ruby team
designs the type system. It'll be gradual, of course, but also it'll be
interesting what adaptations they'll have to make to accommodate existing
code. JavaScript relied on a lot of stringly typed code, so TypeScript added
string literal types. Perhaps Ruby's dynamic, block oriented style could lead
to some interesting decisions in the type system.

Not to mention, the types will most likely be reified as per Ruby's
philosophy.

Super excited for this. Between the JIT and types, Ruby could definitely see a
renaissance in the near future.

~~~
baybal2
What is the rationale of adding types to a language that will still retain all
performance penalties from the need to have dynamic typing code to interact
with non-typed data?

~~~
z1mm32m4n
Who's to say we couldn't use the types to make the runtime faster in the
future?

One of the reasons why Sorbet does both runtime checking[1] more than just
static checking is so that we can know that signatures are accurate, even when
a typed method is called from untyped code.

If the signatures are accurate, a future project could take advantage of
method's signatures to make decisions about how the code should actually be
run. If the signatures lie, then any runtime optimization made using the types
would only be overhead, because the runtime would have to abort the
optimization and fall back to just running the interpreter.

[1]: [https://sorbet.org/docs/runtime](https://sorbet.org/docs/runtime)

~~~
baybal2
I programmed C back in my high school years 14+ years ago. Today I am mostly
using JS because it is the cash crop of the industry, and it made me quite
some money when I was away from electronics business (my main occupation) for
a year after getting troubles with Canadian visas.

To me, it feels that there is a very thick wall in between high level
languages and something with raw data access like C, C++, and D. You either
completely throw out every convenience feature, or go all in on them.

In C, a lot of data access turns into single digit number of load/store or
register access instructions. It is easy to see that it is close to impossible
to add fancy data access functionality on top of that without going from
single cycles to kilocycles.

I was once told "when your try improving a programming language performance,
it eventually turns into C"

P.S. on JIT - it is not given that a JIT language be automatically faster than
a well written interpreter on a modern CPU. One of early tricks of making fast
interpreters was to keep as much of interpreter in cache and data in registers
as possible to benefit from more or less linear execution flow of unoptimised
code in comparison to unpredictable flow of JIT made executable code. Today,
with 16MB caches, I think the benefit of that will be even bigger.

~~~
vnorilo
Types are the means of "improving language performance" without turning into
C. It's all about encoding invariants for the optimizer.

I doubt a competent JIT is ever slower than a competent interpreter, but it
may not be that much faster or worth the workload.

It depends on the size of the primitives. An array language could be close to
1:1, while for a cpu-level instructions you will struggle to reach 1/6 of
JITted perf.

~~~
rurban
You forget this is ruby, which will not have a competent JIT. They have such a
bad JIT with enormous overhead that only very special cases will be faster,
most cases are slower and will wait for locks or be racy.

------
zmmmmm
Fascinating to see the circle turn further back towards strong / static
typing.

One of the major things that has kept me using Groovy over the last 10 years
was the reluctance to leave optional / gradual typing behind. Now, nearly
every major dynamic language has given in and introduced types, so it seems
like this idea of hybrid dynamic/typed languages is now fully mainstream. The
problem of course, is they are all built on a legacy of untyped code, not to
mention giant communities of people with no culture or habit of tying their
code. So it's not clear to me that any amount of added language features can
actually compensate for that.

~~~
sametmax
I get what you mean, but dynamic typing is a feature, just like static typing
is.

Some languages are better from a static POV, and offer some auto features.
Some languages are better from a dynamic POV and offer some hinting feature.

You don't want to type your code to do data exploration and analysis, but you
may want to extend the original project later to something bigger and move on
to types.

There is no such thing as the perfect language for everything anyway. Plus,
it's very good that some languages integrates unnatural features to them, for
the case where you want to go beyond their initial best case scenario. It
won't be perfect, but I don't need perfect, I need programmatic.

The world of programming is vast, the pool of programmers very heterogeneous,
and the constraints are super diverse.

~~~
paganel
> There is no such thing as the perfect language for everything anyway.

People tend to forget this all to easily. For example most of the static type
discussions for the past 10 years have taken place on a website built in a
dynamic programming language, I'm talking about [http://lambda-the-
ultimate.org/](http://lambda-the-ultimate.org/) which afaik is built in Drupal
(i.e. PHP).

~~~
chrisan
To elaborate, I think people don't care what medium they have their
discussions in as long as it works.

Are you not going to use StackOverflow because it is written in C# using
Microsoft servers instead of Go on Linux?

Did you not use Twitter originally because it was built on Rails?

10 years ago... what CMS was popular in a static typed language? Hell today...
what statically typed CMS is popular?

But if that still matters to someone, PHP now supports types!

------
darkdimius
We're collaborating with @yukihiro_matz, @mametter, @soutaro and Jeff Forster
to make sure that types are not disruptive to Ruby. Thus, types are optional.
The intention is to deliver value for unmodified Ruby programs. Hear more from
Matz at
[https://youtu.be/cmOt9HhszCI?t=2148](https://youtu.be/cmOt9HhszCI?t=2148)

~~~
mratzloff
As long as types can be required to be explicit where ambiguous (e.g.,
TypeScript) in the file itself (via a magic comment or similar), I'm all for
it. I am happy to declare types for external calls if I need to.

I have said for awhile that "Ruby with types" would be my favorite language to
work in. I recently returned to Ruby briefly and had to integrate with a
poorly-documented API. I spent more time digging through third-party code
trying to figure out what certain parameters were supposed to be than writing
the program itself.

~~~
uryga
i haven't used it, but have you looked at the Crystal language? i think the
idea is basically "statically typed Ruby".

~~~
mratzloff
I've heard of it and looked at it a bit, but haven't had a chance to use it
yet!

------
vemv
Learning from the clojure.spec success story, what might make/break Sorbet is
its runtime capabilities, aka reification.

* Can I emit typed REST API docs out of sorbet types?

* Can I coerce HTTP params out of sorbet types?

* Can I emit ActiveRecord columns? ActiveModel validations?

* Can I emit generative tests?

You can do all of those (and whatever else you imagine) with clojure.spec in a
DRY manner, i.e. types are defined once, and reused in a variety of contexts.

As a Rails dev, I would greatly value all of those, particularly because
they're practical things directly related to my webdev activity. Ensuring the
type safety of the codebase is great, but also implicitly exercised by an
adequate test suite.

------
kenneth
This is HUGE! Ruby's pace of development continues to impress. It's always
been an impressively practical language and keeps getting better.

------
didibus
It's an interesting turn of event that Ruby, Python and JavaScript are all
getting types.

Meanwhile, I've gotten myself more and more into Clojure. Which now that other
dynamic languages seems to move closer to types, seems to be in a niche in
that Clojure is moving further away from types.

It'll be interesting to see what happens at both extremes and in the happy
middles.

~~~
cutler
>Clojure is moving further away from types

What about clojure.spec?

~~~
didibus
I feel Spec is a part of that "move away from types" which I was talking
about. It's an approach to software documentation, specification and
verification that is at the other end of the spectrum from types.

Clojure seems to have double downed on dynamism and runtime construct, away
from static types. It seems to have made the bet that better software (less
defects, cheaper to maintain and extend, more targeted to the users needs) is
better achieved through:

* Simpler primitives * Immutability * Interactive development * Higher level constructs * Data driven DSLs * Generative testing * Contract specifications * Data specifications

Which are all very good ideas, but they're non traditional compared to formal
static type systems and proofs.

They're used to be more drive behind these in the past, Common Lisp and Eiffel
embody a lot of these ideas, but miss on others. So Clojure is like a new take
trying to fit in all these ideas of interactive, dynamic, safe languages
together a new.

And I just find it interesting, because it is counter current. As others have
pivoted back to static types, Clojure went all in on dynamism.

Time will be the true test, and I'm looking forward from the learnings in all
directions.

~~~
fulafel
It's also an interesting case of language extensibility benefits. Spec is just
a library. And its spritual predecessor, Prismatic/Plumatic Schema, was also
just a library. This enabled the markers of spec to learn from a body of usage
when creating spec with an eye of making it a a standard feature, first as the
spec.alpha library and hopefully now the final form.

An always-on static type system could not develop this way.

------
cutler
The biggest problem for me with gradual typing is code clutter. My favourite
languages are Clojure and Ruby precisely because they reduce code clutter.
What I would prefer, if we are to have types, is for the signatures to go in a
companion file. I've never understood why types have to be inlined. A good IDE
can easily provide the signature in a mouseover or something similar.

~~~
adimitrov
The way to reduce clutter in strongly, statically typed languages is to use
strong, robust type inference.

For example, Java is pretty terrible at type inference (still) and you have to
annotate types almost everywhere (Java 8 had a _very_ tepid improvement on
that front.)

But languages like Haskell and Rust are very good at type inference, and you
almost never actually _need_ to specify the types.

It's still good Haskell style to always annotate the type sigs of top-level
functions. Why? Because they serve as more than just hints to the compiler:
they are part (and a very important part!) of the documentation. _That_ is why
they're in-line. Because A function like

    
    
        zipWith:: [a] -> [b] -> (a -> b -> c) -> [c]
    

tells you what it does in its type signature.

~~~
cutler
There's nothing lost by putting the sig in a companion file and leaving it to
your editor/IDE to provide a popup.

Java 10 and 11 introduced real type inference, at least for local variables
and function parameters.

~~~
Faark
> There's nothing lost by putting the sig in a companion file and leaving it
> to your editor/IDE to provide a popup.

I don't want to go back to having to keep C header file in sync. Your IDE can
hide that information from your as well, if you don't want to see it all the
time.

~~~
mcintyre1994
It's been a while since I wrote Ocaml, but IIRC the compiler yells at you if
your mli files are out-of-date, for whatever that's worth. So keeping them
synced isn't really an issue.

------
tosh
I understand why PHP started to add support for type annotations as the hype
around type annotations (Dart, Flow and Typescript) still was quite strong a
few years ago.

By now I think it is quite obvious that type annotations aren’t as helpful as
initially expected and that a library approach seems more pragmatic and more
powerful. See Clojure + Spec.

The thing is dynamically typed languages with type annotations tend to no
longer feel like dynamically typed languages as the annotations and the
tooling spreads and spreads and spreads. Not easy to put up boundaries.

~~~
cageface
Types are massively helpful with JavaScript. I’ll never write untyped JS again
if I can help it. Switching to typescript has done wonders for my productivity
and code quality.

~~~
techsin101
Tell me few .. to me types were useful for hinting in ide but vscode already
gives good hints

~~~
simplify
Types are not just for autocompleting, but also for making illegal states
unrepresentable[0].

For example, let's say you have Question model with two types: MultipleChoice
and ShortAnswer. In TypeScript you can model it like this:

    
    
        type MultipleChoice = {
          mode: 'mc'
          body: string
          choices: string[]
          expectedAnswer: number
        }
        type ShortAnswer = {
          mode: 'sa'
          body: string
          exampleAnswer: string
        }
    
        type Question = MultipleChoice | ShortAnswer
    

TypeScript's compiler will then enforce data structure consistency across your
entire codebase. For example, if you were rendering a question in React:

    
    
        type Props = {
          question: Question
        }
        const MyComponent = (props: Props) => {
          props.question.body // Ok, since all questions have a body
          props.question.choices // Type error, since only MC has choices
    
          if (props.question.mode === 'mc') {
            props.question.choices // Ok now, since we checked the mode of question
          }
        }
    

You can also use these types to force certain code to always be correct. For
example, if you wanted to display a human-readable version of a Question's
mode, you could write:

    
    
        const prettyQuestionType: Record<Question["mode"], string> = {
          mc: 'Multiple Choice',
          sa: 'Short Answer',
        }
    

and now TypeScript will _force_ prettyQuestionType to contain keys for _all_
modes. That includes when you add a _new_ Question mode later.

Once you learn how to lean on the type checker, you think less about such
details, and your mind becomes freer to think at a higher level, increasing
your overall productivity. There is a learning curve though, so be aware.

[0] [https://fsharpforfunandprofit.com/posts/designing-with-
types...](https://fsharpforfunandprofit.com/posts/designing-with-types-making-
illegal-states-unrepresentable/)

~~~
techsin101
this indeed looks useful. so you can give multiple types by using '|' ? and if
there is vagueness compiler will let you know.. mind blown.

------
b123400
Interesting. I thought the Ruby community generally prefers shorter code, e.g.
`to_s` instead of `to_string`, and yet that type signature is very verbose:
`sig {params(x: Integer).returns(String)}`

~~~
geraldbauer
The type signature in (secure) ruby [1] - an alternative ruby (subset) with
type (optional) annotation - is `sig Integer => String` or `sig [Integer] =>
[String]. Since the sig is just ruby you can create an alias for types e.g. I
= Integer, S = String and than use sig I=>S, for example. [1]:
[https://github.com/s6ruby](https://github.com/s6ruby)

------
rarrrrr
Nice! Reminds me of crystal[0], the LLVM-compiled ruby-alike language.

0: [https://crystal-lang.org](https://crystal-lang.org)

~~~
leshow
Except crystal's type system seems much more capable & powerful.

------
vemv
Partnering with Ruby Core is a bit dubious for a project which is still closed
source.

Why the privacy? Are programmers too dumb to understand something is a beta?

What if in the end adoption is marginal and Ruby Core's time was wasted?

Best adoption is organic, not hyped up.

~~~
steveklabnik
From the slides that are linked in the tweet in the tweet:
[https://sorbet.run/talks/RubyKaigi2019/#/45](https://sorbet.run/talks/RubyKaigi2019/#/45)

------
snrji
The trend of adding type annotations to dynamically typed languages is now
unstoppable. I wonder if some more exotic features (eg. side effects handling,
monads or dependent types) will ever become mainstream in the feature.

~~~
Guthur
It's hardly unstoppable its been there for literally decades. Common lisp had
it for a very long time for example and has a few compiler implementations
that are really quite sophisticated.

The problem is that most popular dynamic languages are really quite terrible.
They have atrocious runtime environments and usually quite limiting language
semantics.

~~~
snrji
It was not mainstream back then.

I agree that most popular dynamic are quite terrible. But, honestly, I think
the real problem is not the particular implementations, but the whole idea of
dynamic typing. At first it did make sense, but now that compiler writers have
figured out "cheap" and general type inference, I don't see the point anymore.

However, I use Python on a daily basis because I have no decent alternative
for the libraries I use.

------
ricardobeat
I don't use Ruby day-to-day other than a few small tools, but why not focus
efforts on evolving Crystal [1] to make it more suited for rapid web
development? It already has a powerful type system and incredible performance,
and should be an easy transition for rubyists.

[1] [https://crystal-lang.org/](https://crystal-lang.org/)

~~~
technion
Why should the people who built and maintain Ruby focus their efforts on a
different language?

~~~
ricardobeat
You can ask the creator himself:
[https://github.com/mruby/mruby](https://github.com/mruby/mruby)

------
ekvintroj
There is something similar (but more powerful) for Smalltalk, it collects the
types as you run the code and then it is used to improve the refactors.

Check it out.
[https://github.com/hernanwilkinson/LiveTyping](https://github.com/hernanwilkinson/LiveTyping)

------
gkemmey
Why do these efforts have to move into Ruby proper? Why can't sorbet or steep
stay their own thing, and if it solves your Stripe-like-codebase problems,
great. What I don't see a lot of here (or in general these days) is advocacy
for the advantages of dynamic typing. And if you're objective, there most
certainly are, even if they're not worth the disadvantages, or don't surpass
the advantages of static typing for you, personally.

But Ruby used to advocate for them, and it's definitely what drew me in. I
find it disappointing that we're moving away from that. More and more, it
seems we’re attempting to make Ruby all things to all people. Which eventually
makes it the right thing for no one.

~~~
detaro
How do optional typing annotations break ruby/Python/... for you?

~~~
gkemmey
Well, I think there's a bit of mandatory-ness that comes with adding it to
Ruby itself. Sounds like the standard library is going to ship with rbi files
defined, for instance. Plus, tools for generating rbi files. On some level,
it's an endorsement to do things this way, right? And that's before it
(potentially) becomes a community practice to do so.

If it's not, why not leave these solutions in gems?

Btw, I don't think static typing alone is Ruby becoming all things to all
people. In recent history, it's also aliasing `Enumerable#filter` to
`Enumerable#select`, numbered block arguments, a shorthand special notation
for `Object#method` -- it feels like a trend of "hey these other languages do
this, we should too". I'm not convinced that's always the case.

------
geraldbauer
FYI: For an alternative ruby (subset) with type annotations today see sruby,
that is, secure ruby - [https://github.com/s6ruby](https://github.com/s6ruby)

------
fulafel
Ruby already had types, no? This is about static typing.

~~~
viraptor
If you're going for precision, then probably: type-annotations. The runtime
doesn't change with sorbet. All the verification is via an external tool. So
there's no static typing - your code can still violate the rules.

------
virtualwhys
Great for Ruby (OP was arguably the most important compiler dev behind Martin
Odersky on the Dotty/Scala 3 project), types for the win.

------
phaedryx
I recommend whatching "Ruby3: What's Missing?", a presentation Matz gave
earlier this month:
[https://www.youtube.com/watch?v=cmOt9HhszCI](https://www.youtube.com/watch?v=cmOt9HhszCI)

This might be misleading. That is, jump to around the 29 minute mark where he
talks about the type profiler and .rbi file stuff.

~~~
aasasd
As a user of Homebrew, I just wonder if Ruby's ever going to have performance.

~~~
localhostdotdev
homebrew's performance is mostly network (git / http / https) and compilation
times when needed.

also for some reason homebrew really likes to updates its index all the time
(I think it got tamed in the newest version), but setting
HOMEBREW_NO_AUTO_UPDATE to 1 helps a lot.

~~~
aasasd
With HOMEBREW_NO_AUTO_UPDATE and HOMEBREW_NO_GITHUB_API, it still gobbles up a
core for a full minute to find a substring in a list of strings. Even if it
looks through directories for this, I can't imagine how this task would
perform so badly. It's not system cpu time primarily.

------
geraldbauer
FYI: The RubyKaigi 2019 Progress Report on Ruby 3 Talk Slides have more (from
the source) info. See the slides titled "Static Analysis" [1]

Ruby 3 static analysis will have four items:

1\. Type signature format 2\. Level-1 type checking tool 3\. Type signature
profiling / prototyping tool 4\. Level-2 type checking tools

and so on. [1]:
[https://docs.google.com/presentation/d/1z_5JT0-MJySGn6UGrtda...](https://docs.google.com/presentation/d/1z_5JT0-MJySGn6UGrtdafK1oj9kGSO5sGlTtEQJz0JU/view#slide=id.g57cf166414_14_5)

------
joelbluminator
My concern about all of this is that it might lead to basically two ruby
communities; Rails and Rails devs will mostly keep writing type free code (dhh
has always indicated he's not a fan of types), but a lot of other rubyists
will gradually introduce types into their code. This could create two
different ecosystems with different gems, best practices, blogs etc etc etc.
We will see how it plays out but I'm quite conflicted about this one. The good
thing is that it's optional.

~~~
jez
It’s not in the tweet but we specifically covered that it’s possible to type
check Rails in our talk actually:

\-
[https://sorbet.run/talks/RubyKaigi2019/#/53](https://sorbet.run/talks/RubyKaigi2019/#/53)

\-
[https://sorbet.run/talks/RubyKaigi2019/#/55](https://sorbet.run/talks/RubyKaigi2019/#/55)

So I don’t think that the divide will be at Rails. And more than that, I think
there will be very little divide at all. Sorbet is designed to be gradual, so
it works 100% fine with untyped code:

[https://sorbet.org/docs/gradual](https://sorbet.org/docs/gradual)

~~~
joelbluminator
Hi thanks for this! Could you shed more light on the last part where they show
parts of Rails, Gitlab etc are already typed? How is this possible?

~~~
z1mm32m4n
Sorbet has multiple Strictness Levels[1]. The two most relevant ones are
`typed: false` and `typed: true`. `typed: false` is the default level and at
this level only errors related to constants are reported, like this one:

[https://sorbet.run/talks/RubyKaigi2019/#/14](https://sorbet.run/talks/RubyKaigi2019/#/14)

But we'd like to catch more than just errors related to constants, like those
related to missing methods, or calling a method with the wrong arguments.
Errors like these are only reported in files marked `typed: true`:

[https://sorbet.run/talks/RubyKaigi2019/#/19](https://sorbet.run/talks/RubyKaigi2019/#/19)

Sorbet doesn't need to have method signatures to know whether a method exists
at all, or what arity that method has.

But more than that, Sorbet ships with type definitions for the standard
library. So you don't even need to start annotating your methods to type check
the body of your methods, because most of the body of your methods are calling
standard library things (arrays, hashes, map, each, etc.).

The statistics in those slides are sharing "out of the box, what's the highest
strictness level that could be added to a file without introducing errors?" So
ideally an entire project be made `typed: true`, but Sorbet can be adopted
gradually, so a project can exist in a partial state of typedness. We wanted
to see how painful it would be to adopt Sorbet in a handful of large, open
source rails projects, and it turned out to be not that bad.

[1]: [https://sorbet.org/docs/static#file-level-granularity-
strict...](https://sorbet.org/docs/static#file-level-granularity-strictness-
levels)

~~~
theredbox
Can you comment something about the possibility of Ruby getting faster because
of Sorbet ? Can it be combined with DragonRuby or other compilers that would
produce more optimized Ruby programs?

------
cutler
Instead of:

    
    
      sig {params(name: String).returns(Integer)}
    

... why not simply:

    
    
      sig {name: String, returns: Integer}

~~~
geraldbauer
Instead of:

    
    
       sig {params(name: String).returns(Integer)}
    

... why not simply:

    
    
       sig [String]=>[Integer]
    

Yes, that's just ruby - see [https://github.com/s6ruby/ruby-to-
michelson/blob/master/cont...](https://github.com/s6ruby/ruby-to-
michelson/blob/master/contracts/token.rb#L32) for example for live running
code (in secure ruby) :-)

~~~
bhuga
At the very least, sigs need to be in blocks so they can be lazy and not
require that all constants in any sig be loaded at require time.

It was a design decision that all type annotation arguments be named as
opposed to positional. As one example why, it makes the error messages better.
You can always say "You're missing a type declaration for parameter 'foo'" as
opposed to "You have four positional arguments and 3 types".

We could probably still bikeshed our annotations inside the `sig { ... }`. I'm
not sure we'd make constants with unicode like BigMap‹Address→Account› for
generics, though, how do you even type that? :)

~~~
geraldbauer
For the "do not require" the type annotations / signatures so they can be lazy
I would use / recommend a language pragma and not a block. Learn more about
language pragmas (works kind like a pre-processor) :-) -
[https://github.com/s6ruby/pragmas](https://github.com/s6ruby/pragmas) I think
you already have made-up your own "magic comments" / language pragma e.g. #
type: true and so on.

> I'm not sure we'd make constants with unicode like > BigMap‹Address→Account›
> for generics, though, how do > you even type that? :)

I see you managed to type it! What's your secret? :-). By the way, you can use
the alternate ASCII-style e.g. BigMap.of(Address=>Account).

------
cocochanel
Why is everything moving to types?

~~~
jaequery
I don’t know but I hate it. Not sure if I’m in the minority but it sure feels
like it. In an ideal world. I feel that types are something that should be
dealt with at the IDE level. In fact, there so many things that can be done at
that level, but no one has really been brave enough to do so I suppose.

~~~
tomc1985
So, what, everyone standardizes around an IDE then? You really think that's
gonna unite the vim and emacs camps?

I'm personally tired of staring at variables trying to figure out what they're
supposed to be, then having to dive into source to see how its used. C/C++/C#
solved that problem, why are we still dealing with it?

~~~
Shish2k
C had some typing, but I'm not going to call it "solved" until "numberOfHats =
distanceInPixels + weightInKg" is considered a compile-time error due to the
three "int" values being incompatible; but "numberOfHats = aliceHatCount +
bobHatCount" is acceptable.

How does nobody(?) support this yet?

Python supports some parts: you can subclass int, and you get all of the int
methods like addition and subtraction for free, but "distanceInKm +
distanceInKm" gives you an int instead of a distanceInKm; and "distanceInKm +
distanceInMiles" gives you an int instead of an error.

Rust also has partial support but from the other end: distanceInMiles and
distanceInKm can be two distinct subclasses of int, and adding them together
is a compile time error. But also adding distanceInMiles with distanceInMiles
is a compiler error, because these are basically "completely new classes"
rather than "subclasses of int", and so you have to implement add / subtract /
stringify / etc for yourself for every type D: (I'm fairly new to Rust so if
there is a shortcut there that I'm missing please do point it out)

~~~
59nadir
Every language that has generics supports this via phantom type variables that
can encode extra information only in the type system alongside some other
type, or with a specific newtype keyword that effectively does the same:

    
    
        newtype Pixel = Pixel Int
        newtype Em = Em Int
    
        pixelWidthToEm :: Pixel -> Em
        pixelWidthToEm (Pixel px) = Em px
    

You can try to call `pixelWidthToEm` with anything other than pixels and it
won't work.

More dynamically, with an open type variable that only exists in the type
system:

    
    
        data User a =
          User { name :: String, socialSecurityNumber :: String }
    
        data LogSafe
        data LogUnsafe
    
        logUser :: User LogSafe -> IO ()
        logUser = undefined
    
        makeUserLogSafe :: User LogUnsafe -> User LogSafe
        makeUserLogSafe = undefined
    

We can never log the user unless the user is deemed LogSafe and we make
functions that produce log safe users that you have to call before hand, in
order to make sure that sensitive data isn't printed to logs.

These are things that have been around for a long time in almost every type
system, but people's general lack of interest in using type systems to help
them conspires to keep them in the dark.

Here's how you can create a number type distinct from other number types in
TypeScript:

    
    
        type DistanceInPixels = number & { readonly __newtype__: "DistanceInPixels" }
    

And a type alias that allows you to create them:

    
    
        export type Newtype<T, Tag extends string> = T & { readonly __newtype__: Tag }
        type Pixels = Newtype<number, "Pixels">

------
geraldbauer
FYI: You can add the missing Bool type today :-), use the safebool library /
gem - [https://github.com/s6ruby/safebool](https://github.com/s6ruby/safebool)

~~~
Dirlewanger
Are TrueClass/FalseClass being united under one class for 3?

------
inopinatus
It looks like they've conflated type with class. If so, that's the antithesis
of duck typing. The impedence mismatch to Ruby seems to me an overwhelming
contraindication.

~~~
coldtea
Well, classes are types in a language where everything is an object. It's the
same in Smalltalk, no?

~~~
inopinatus
That is exactly the category error I am calling out.

In a duck-typed language, type is defined by the willingness of a message
receiver to receive that message. Class, inheritance, composition are all
means to achieve this, but the type of an object is determined by its
signature, not its ancestor chain.

------
rswillif
All of these beneficial refinements are meaningless if increasing performance
optimization in the runtime isn't made more of a priority.

------
sunasra
This is super cool. I would expect the same support for Rails after Ruby 3
release

------
localhostdotdev
small discussion that was marked as dupe
[https://news.ycombinator.com/item?id=19696669](https://news.ycombinator.com/item?id=19696669)

------
gigatexal
I hope Python 4 goes this route.

------
auvi
when Ruby 3.0 will be released? 2022 Christmas?

~~~
rajangdavis
2019?

~~~
lloeki
2019 is 2.7. GP is counting as if version numbers were decimals (2.8 in 2020,
2.9 in 2021, 3.0 in 2022 when it could just as well be 2.10)

------
jaequery
Types will be optional right? Otherwise I am gonna have to jump ship sadly.

~~~
darkdimius
See
[https://news.ycombinator.com/item?id=19697581](https://news.ycombinator.com/item?id=19697581)

