frontpage.
newsnewestaskshowjobs

Made with ♥ by @iamnishanth

Open Source @Github

fp.

OpenCiv3: Open-source, cross-platform reimagining of Civilization III

https://openciv3.org/
553•klaussilveira•10h ago•157 comments

The Waymo World Model

https://waymo.com/blog/2026/02/the-waymo-world-model-a-new-frontier-for-autonomous-driving-simula...
876•xnx•15h ago•532 comments

How we made geo joins 400× faster with H3 indexes

https://floedb.ai/blog/how-we-made-geo-joins-400-faster-with-h3-indexes
79•matheusalmeida•1d ago•18 comments

What Is Ruliology?

https://writings.stephenwolfram.com/2026/01/what-is-ruliology/
8•helloplanets•4d ago•3 comments

Unseen Footage of Atari Battlezone Arcade Cabinet Production

https://arcadeblogger.com/2026/02/02/unseen-footage-of-atari-battlezone-cabinet-production/
13•videotopia•3d ago•0 comments

Show HN: Look Ma, No Linux: Shell, App Installer, Vi, Cc on ESP32-S3 / BreezyBox

https://github.com/valdanylchuk/breezydemo
191•isitcontent•10h ago•24 comments

Monty: A minimal, secure Python interpreter written in Rust for use by AI

https://github.com/pydantic/monty
190•dmpetrov•10h ago•84 comments

Show HN: I spent 4 years building a UI design tool with only the features I use

https://vecti.com
303•vecti•12h ago•133 comments

Microsoft open-sources LiteBox, a security-focused library OS

https://github.com/microsoft/litebox
347•aktau•16h ago•169 comments

Sheldon Brown's Bicycle Technical Info

https://www.sheldonbrown.com/
347•ostacke•16h ago•90 comments

Dark Alley Mathematics

https://blog.szczepan.org/blog/three-points/
75•quibono•4d ago•16 comments

Hackers (1995) Animated Experience

https://hackers-1995.vercel.app/
444•todsacerdoti•18h ago•226 comments

Show HN: If you lose your memory, how to regain access to your computer?

https://eljojo.github.io/rememory/
242•eljojo•13h ago•148 comments

PC Floppy Copy Protection: Vault Prolok

https://martypc.blogspot.com/2024/09/pc-floppy-copy-protection-vault-prolok.html
46•kmm•4d ago•3 comments

Delimited Continuations vs. Lwt for Threads

https://mirageos.org/blog/delimcc-vs-lwt
17•romes•4d ago•2 comments

An Update on Heroku

https://www.heroku.com/blog/an-update-on-heroku/
379•lstoll•16h ago•258 comments

How to effectively write quality code with AI

https://heidenstedt.org/posts/2026/how-to-effectively-write-quality-code-with-ai/
225•i5heu•13h ago•171 comments

Why I Joined OpenAI

https://www.brendangregg.com/blog/2026-02-07/why-i-joined-openai.html
103•SerCe•6h ago•84 comments

Learning from context is harder than we thought

https://hy.tencent.com/research/100025?langVersion=en
162•limoce•3d ago•85 comments

I spent 5 years in DevOps – Solutions engineering gave me what I was missing

https://infisical.com/blog/devops-to-solutions-engineering
131•vmatsiiako•15h ago•56 comments

Introducing the Developer Knowledge API and MCP Server

https://developers.googleblog.com/introducing-the-developer-knowledge-api-and-mcp-server/
41•gfortaine•8h ago•11 comments

Show HN: R3forth, a ColorForth-inspired language with a tiny VM

https://github.com/phreda4/r3
63•phreda4•9h ago•11 comments

Female Asian Elephant Calf Born at the Smithsonian National Zoo

https://www.si.edu/newsdesk/releases/female-asian-elephant-calf-born-smithsonians-national-zoo-an...
20•gmays•5h ago•3 comments

Show HN: ARM64 Android Dev Kit

https://github.com/denuoweb/ARM64-ADK
14•denuoweb•1d ago•2 comments

Understanding Neural Network, Visually

https://visualrambling.space/neural-network/
262•surprisetalk•3d ago•35 comments

I now assume that all ads on Apple news are scams

https://kirkville.com/i-now-assume-that-all-ads-on-apple-news-are-scams/
1035•cdrnsf•19h ago•428 comments

Zlob.h 100% POSIX and glibc compatible globbing lib that is faste and better

https://github.com/dmtrKovalenko/zlob
6•neogoose•2h ago•3 comments

FORTH? Really!?

https://rescrv.net/w/2026/02/06/associative
56•rescrv•18h ago•19 comments

Show HN: Smooth CLI – Token-efficient browser for AI agents

https://docs.smooth.sh/cli/overview
85•antves•1d ago•63 comments

WebView performance significantly slower than PWA

https://issues.chromium.org/issues/40817676
20•denysonique•6h ago•3 comments
Open in hackernews

PHP compile time generics: yay or nay?

https://thephp.foundation/blog/2025/08/05/compile-generics/
98•moebrowne•6mo ago

Comments

tobinfekkes•6mo ago
Can someone smarter than me explain what they mean by "reified generics", "erased generics", and a use case for when to use one over the other?
gloryjulio•6mo ago
Example, Java is using erased generics. Once the code is compiled, the generics information is no longer in the bytecode. List<String> becomes List<>. This is called type erasure.

C# is using reified generics where this information is preserved. List<String> is still List<String> after compilation

branko_d•6mo ago
And as a consequence, C# can pack the value types directly in the generic data structure, instead of holding references to heap-allocated objects.

This is very important both for cache locality and for minimizing garbage collector pressure.

svieira•6mo ago
And Java has been working on Project Valhalla for ~20 years to retrofit the ability to do this to the existing Java language...
metadat•6mo ago
Reified Generics doesn't seem to be a goal mentioned on the project website- Am I missing something?

https://openjdk.org/projects/valhalla/

There is an interesting article which mentions reification, but that's all I could locate.

How We Got the Generics We Have (Or, how I learned to stop worrying and love erasure)

https://openjdk.org/projects/valhalla/design-notes/in-defens...

svieira•6mo ago
Reified generics aren't on the board, but a solution to:

> And as a consequence, C# can pack the value types directly in the generic data structure, instead of holding references to heap-allocated objects.

is what Project Valhalla is all about. (Java doesn't have a good reason for being able to do `new T` at the moment, but being able to treat a generic container as optimizable-over-structs is an explicit goal).

pjmlp•6mo ago
The goal for Valhalla is value types, reiifed generics if they ever happen is still open.

The project was announced in July 2014, hardly 20 years.

Also the reason they are still at it, is how to run old JARs withouth breaking semantics, in a Valhalla enabled JVM.

Had Oracle wanted to do a Python 3, Valhalla would have been done by now, however we all know how it went down, and Java 9 was already impactful enough to the ecosystem.

ygra•6mo ago
> The goal for Valhalla is value types, reified generics if they ever happen is still open.

But if they want the List<int> use case to be fast they basically have to keep this information at runtime and will have to make changes to how objects are laid out in memory. I'm not sure there's a good way around that if you want List<int> to be backed by an int[] and `get` returning an int instead of an Object. This may or may not be available to developers and remain internal to the JVM in the beginning, but I think it's necessary to enable the desired performance gains.

They also state on the website: »Supplementary changes to Java’s generics will carry these performance gains into generic APIs.«

pjmlp•5mo ago
Haskell and OCaml are two runtimes that do just good enough with type erasure for how the polymorphic types get implemented across their implementations.

Probably MLton is the only implementation that actually does it the C++ and Rust way.

So lets see how far they go.

I always considered it was a mistake for Java to ignore what GC enabled languages were doing at the time, Eiffel, Modula-3, Oberon and frieds, which they naturally looked into given their influences, but it wasn't deemed necessary for the original Java purposes of being a settop box and applets language.

Now we have a good case of what happens when we tried to retrofit such critical features after decades of field usage, a lesson that Go folks apparently failed to learn as well.

kgeist•6mo ago
With reified generics, you can also do "new T[]" because the type is known at runtime. With type erasure, you can't do that.
SPBS•5mo ago
> And as a consequence, C# can pack the value types directly in the generic data structure, instead of holding references to heap-allocated objects.

> This is very important both for cache locality and for minimizing garbage collector pressure.

How is C# just not straight-up faster than Java then? Instead of both language punching around the same weight on benchmarks? Doesn't cache locality like, have a huge effect on performance?

actionfromafar•5mo ago
I have no answer except that Java Hotspot JIT seems to be almost too good to be true. I guess it's my way of saying I would also like to know why C# isn't just plain faster than Java.
no_wizard•5mo ago
There’s more to the speed of a language than this one thing.

In many aspects C# is. I remember listening to a talk from Microsoft (admittedly) where using 100% latest features was on average faster than Java

PaulGaspardo•6mo ago
Incidentally if you do what they're proposing for PHP in Java (where you define a non-generic subclass of a generic type), the actual generic type parameters actually are in the bytecode, and depending on the static type you use to reference it, may or may not be enforced...

   public class StringList extends java.util.ArrayList<String> {
       public static void main(String[] args) throws Exception {
           StringList asStringList = new StringList();
           java.util.ArrayList<Integer> asArrayList = (java.util.ArrayList<Integer>)(Object)asStringList;
           System.out.println("It knows it's an ArrayList<String>: " + java.util.Arrays.toString(((java.lang.reflect.ParameterizedType)asArrayList.getClass().getGenericSuperclass()).getActualTypeArguments()));
           System.out.println("But you can save and store Integers in it:");
           asArrayList.add(42);
           System.out.println(asArrayList.get(0));
           System.out.println(asArrayList.get(0).getClass());
           System.out.println("Unless it's static type is StringArrayList:");
           System.out.println(asStringList.get(0));
       }
   }
That prints out:

   It knows it's an ArrayList<String>: [class java.lang.String]
   But you can save and store Integers in it:
   42
   class java.lang.Integer
   Unless it's static type is StringArrayList:
   Exception in thread "main" java.lang.ClassCastException: class java.lang.Integer cannot be cast to class java.lang.String (java.lang.Integer and java.lang.String are in module java.base of loader 'bootstrap')
    at StringList.main(StringList.java:11)
Gibbon1•6mo ago
I'm not smarter than you but.

I believe the terms reified generics and erased generics is the type sweaty donkey ball terminology you get for professional CS academics.

Sticking my neck out further.

Reified generics means the type is available at run time. In C# you can write if(obj.GetType() == typeof(typename))

Erased generics the type information is not available at run time. That's the way Java does it and it kinda sucks.

p1necone•6mo ago
Academics invent short names for common (in their field) concepts not because they're 'sweaty' but because if the thing you're going to mention in every second paragraph in a good chunk of the communication you do with other people working on the same topic requires a full sentence to explain you're going to A. get really annoyed at having to type it out all the time and B. probably explain it slightly differently every time and confuse people.

Academic jargon isn't invented to be elitist, it's invented to improve communication.

(of course there's a good chance you understand this already, and you're just making a dumb joke, but I figured I'd explain this anyway for the benefit of everyone reading)

fuzzy_biscuit•6mo ago
I don't take issue with the naming but with the names that feel a bit beyond my ken. "Erased" makes sense when explained but not before. "Reified" is a word I simply do not use so it feels like academia run amok.

Regardless, I recognize myself as the point of failure, but those names do strike me as academia speak, though better than some/many. <shrug>

klodolph•6mo ago
Another shrug, but part of it is that the PL community (programming language community) is pretty deep into its own jargon that doesn’t have as much overlap as you might think, with other subfields of computer science.

People describe a type system as “not well-founded” or “unsound” and those are specific jabs at the axioms, and people talk about “system F” or “type erasure” or “reification”. Polymorphism can be “ad-hoc” or “parametric”, and type parameters can be invariant, covariant, and contravariant. It’s just a lot of jargon and I think the main reason it’s not intuitive to people outside the right fields is that the actual concepts are mostly unfamiliar.

bawolff•6mo ago
> Another shrug, but part of it is that the PL community (programming language community) is pretty deep into its own jargon that doesn’t have as much overlap as you might think, with other subfields of computer science.

The word reified dates back to the 1800s. It isn't the most common word, but it also definitely wasn't invented by the programming language community.

peterfirefly•5mo ago
It was (and is) used a lot by philosophers and there was a large overlap between a certain class of philosophers and a certain class of mathematicians who developed early type theory. Any type theorist who knows his literature will run into reification very early on.
skissane•6mo ago
> Erased generics the type information is not available at run time. That's the way Java does it and it kinda sucks.

To be more precise: in Java, generics on class/method/field declarations are available at runtime via reflection. The issue is that they aren’t available for instances. So a java.util.ArrayList<java.lang.String> instance is indistinguishable at runtime from a java.util.ArrayList<java.lang.Object> instance

mrkeen•6mo ago
> Erased generics the type information is not available at run time. That's the way Java does it and it kinda sucks.

In a good statically-typed language you don't need runtime type information. It could be a Void in the bytecode for all I care, as long as it behaves correctly.

> obj.GetType() == typeof(typename)

In a statically-typed language, this can be optimised away to a bool at compile time.

Gibbon1•5mo ago
Oh absolutely not true AT ALL.
positr0n•5mo ago
Occasionally it is really useful to be able to do something like `new T()`. Without reified generics that is not possible.
mrkeen•5mo ago
new T? What's wrong with the old one?

Jokes aside, what's the use case for not knowing what T is until runtime?

chuckadams•5mo ago
Pretty much all polymorphism works by not knowing the concrete type til runtime. If you have an Animal reference to a Dog instance, any method you call on it is resolved at runtime, because the reference knows the type. Reified generics do the same for type parameters, whereas erased types are only used for type checking at compile time.
mrkeen•5mo ago
Nah I think I'd just prefer to figure out the types in type-checking phase, then erase and get on with things.

I don't buy that most polymorphism is dynamic.

No example of 'new T()' (which wouldn't be improved by static typing was given) so I got nothing else to say.

meindnoch•5mo ago
With reified generics, the code

  class Foo<X> {
    X x;
  }

  Foo<int> fooInt;
  fooInt.x = 5;
  Foo<float> fooFloat;
  fooFloat.x = 5.0;
compiles to:

  class Foo_int {
    int x;
  }

  class Foo_float {
    float x;
  }

  Foo_int fooInt;
  fooInt.x = 5;
  Foo_float fooFloat;
  fooFloat.x = 5.0;

On the other hand, erased generics compiles to this:

  class Foo {
    void* x;
  }

  Foo fooInt;
  fooInt.x = new int(5);
  Foo fooFloat;
  fooFloat.x = new float(5.0);
twiss•6mo ago
I may be missing something about how the PHP compiler/interpreter works, but I don't quite understand why this is apparently feasible to implement:

    class BlogPostRepository extends BaseRepository<BlogPost> { ... }
    $repo = new BlogPostRepository();
but the following would be very hard:

    $repo = new Repository<BlogPost>();
They write that the latter would need runtime support, instead of only compile time support. But why couldn't the latter be (compile time) syntactic sugar for the former, so to speak?

(As long as you don't allow the generic parameter to be dynamic / unknown at compile time, of course.)

jasone•6mo ago
The former merely exposes a `BlogPostRepository` class. The latter requires some mechanism for creating a generic object of concrete type, which is a lot bigger change to the implementation. Does each parametrized generic type have its own implementation? Or does each object have sufficient RTTI to dynamically dispatch? And what are the implications for module API data structures? Etc. In other words, this limitation avoids tremendously disruptive implementation impacts. Not pretty, but we're talking PHP here anyway. ;-)
baobun•6mo ago
Usually you are right. I assume the inability to sugar would be that "because PHP", the value/type of BlogPost can not be derived at compile-time?
SoftTalker•6mo ago
In the sense of an affirmative vote, the proper word is "yea."
calvinmorrison•6mo ago
write PHP a lot. every day.

I wish we had typed arrays. Totally not gonna happen, theres been RFCs but I have enough boilerplate classes that are like

Class Option Class Options implements Iterator, countable, etc.

Options[0], Options[1], Options[2]

or Options->getOption('some.option.something');

A lot of wrapper stuff like that is semi tedious, the implementation can vary wildly.

Also because a lot of times in php you start with a generic array and decide you need structure around it so you implement a class, then you need an array of class,

Not to mention a bunch of WSDLs that autogenerate ArrayOfString classes...

wesammikhail•6mo ago
Nailed it.

This is the core problem with PHP for me.I love PHP and use it every day. Part of that is the strength and versatility of the arrays implementation (i.e. hashmap). However, the problem is always the fact that an array cant be typed.

IF they could just introduce that, it would solve 80% of user-land issues over night.

bakje•5mo ago
We used to have a lot of classes like that, but for us PHPStan is sufficient and we effectively have generics now through static analysis warning us of improper usage of types in our CI and IDEs.

Is this not suitable for you?

makeitdouble•5mo ago
Use cases might be different than parent, but PHPStan while being the best tool available is far from perfect, there's still a lo of logic it can't follow. First class citizen array type support baked into the language would hopefully behave better.
bakje•5mo ago
Oh absolutely, but simply for typed arrays it should suffice
yuliyp•6mo ago
In Hack, collection objects were one of the biggest early mistakes that the took a huge amount of effort to undo. It turns out that the copy-on-write semantics of PHP array were extremely important for performance and good APIs. Being able to pass arrays to things without fear of mutation allowed for tons of optimizations and not needing to copy things just in case. This is why Hack switched to using `dict`, `vec`, and `keyset` rather than collection objects.

More generally, it's weird to see a whole blog post about generics for PHP not even mentioning Hack's generics designs. A lot of thought and iteration went into this like 5-10 years ago.

See https://docs.hhvm.com/hack/arrays-and-collections/object-col... and https://docs.hhvm.com/hack/arrays-and-collections/vec-keyset...

maxloh•6mo ago
I thought Hack is dead or not intended for public use anymore.

But after some quick checking, I learned that Hack is still actively maintained, surprisingly.

phplovesong•6mo ago
It is, and Hack exists ONLY because PHP was not cutting it for a big project like facebook. Its the biggest example out there why should not use PHP for anything close to, say 10% of facebook scale.
nolok•6mo ago
> Its the biggest example out there why should not use PHP for anything close to, say 10% of facebook scale.

What a weird take to base your current belief on something that happened more than a decade ago.

Not only the condition for Hack creation (speed, memory usage and strict type checking) have been fixed a long time ago since php 7.0

But also if you reach 10% of facebook scale, it doesn't matter what language you used, you will need to rewrite anyway.

Show me a company where PHP is the issue because they reached 10% of facebook scale, and what you're showing is a company that succeeded thanks to PHP. Applies to other language the same. Picking your stack based on "but what if I reach that scale" has to be the mother of all premature optimisations.

phplovesong•5mo ago
There are many large projects out there written in say, Java (the old boring dog) that did not have to rewrite. I can add C# as another traditional corpororate language.

There are many others too. PHP not so much.

nolok•5mo ago
Yeah you will have to provide a list of "10% of facebook scale" projects using those language and didn't need to have any rewrite
4ndrewl•6mo ago
I doubt anyone here is working to 1% of fb scale, let alone 10%.

The answer to "why Hack" needs to be viewed in the historical context of "when Hack" and what was happening (or not) in the php ecosystem at that time.

Things have changed a lot since, in terms of performance, language longevity, ecosystem etc. Its a perfectly reasonable language to adopt for many orgs.

rob74•6mo ago
More specifically, Hack was developed during the time when it looked like the PHP project wasn't going anywhere (it was stuck at version 5.x for ten years while version 6 was in the works, then abandoned, then version 7 was developed based on version 5 and finally released in 2015).
mrkeen•5mo ago
Given that Hack had generics as early as 2014, it seemed that those who were worried about PHP being stuck were right.

Unless I'm misunderstanding what this proposal (not finished artifact) is about.

ZiiS•5mo ago
Some people here work at (exactly) 100% of fb scale.
mrkeen•5mo ago
Seems to line up with what the authors say:

  At Facebook scale — with thousands of engineers shipping new code twice a day — slowdowns like these are even more problematic.

  https://engineering.fb.com/2014/03/20/developer-tools/hack-a-new-programming-language-for-hhvm/
meindnoch•5mo ago
The backend of Facebook's frontend is written in Hack. For longest time, I wouldn't believe it... and then I saw the code with my own eyes.
somat•6mo ago
I am not much of a programmer so I was trying to figure out what generics are. And I am sure they are great, but my inner gremlin goes in sarcastic tone "we want these elaborate type systems, but we also want typeless because that is far more convenient to use, so we invented generics, a method to untype your type system"

But really while I was reading up on what generics are I went, isn't that just python, strongly typed but your functions don't have built in type checks.

tibbar•6mo ago
As you say, generics really only apply to typed languages, and they help solve very legitimate annoyance in most of those languages -- you often have some library helper or algorithm that can apply to a wide range of things, but those things differ in some way that's irrelevant to the algorithm.

For example, a mergesort algorithm works on any kind of array, as long as you can compare the elements in the array to each other. There's no point in re-implementing the algorithm for each kind of array. Yet, without generics, you'd need to do just that. At the same time, the generated code for sorting each different kind of array might need to be a little different - comparing strings and floats isn't the same assembly, for instance. So the programming language and compiler work together: you specify the algorithm once in a certain way, and the compiler can generate the right version of algorithm for each way that you need to use it.

There are many, many good reasons why you might want to work in a typed language, even though specifying the types is a bit of extra book-keeping; generics are one way to keep the pointless work down. Of course, if you can get away with a python script, there's no need to bother with all this typing business just yet, either.

masklinn•6mo ago
> "we want these elaborate type systems, but we also want typeless because that is far more convenient to use, so we invented generics, a method to untype your type system"

It's rather the exact opposite. Parametric types are a way to properly type "deeply" instead of just the topmost layer. Just like inference, type parameters don't remove types.

> isn't that just python, strongly typed but your functions don't have built in type checks.

That doesn't really make any sense? Static types mean you don't have runtime type checks, since the types are known statically.

oaiey•5mo ago
I also do not understand the motion that generics are loosely typed or dynamic. I think people mix this up, since it makes the frameworks and libraries more dynamic (in a strictly typed way) but that is a very different dynamic than language dynamic.
noelwelsh•6mo ago
The introduction to me reads as very confused:

One of the most sought-after features for PHP is Generics: The ability to have a type that takes another type as a parameter. It's a feature found in most compiled languages by now, but implementing generics in an interpreted language like PHP, where all the type checking would have to be done at runtime, has always proven Really Really Hard(tm), Really Really Slow(tm), or both.

* The topic of the article is implementing generics at compile time, but this claims that PHP is not compiled.

* Type checking is orthogonal to compilation vs interpreter.

* Types are not checked at runtime. It is kinda the point of types that they are checked before code runs. Runtime checks are on values. You can reify types at runtime but this breaks a useful property of generics (parametricity) and it prevents the very useful feature of types without a runtime representation (often known as newtypes).

* If you want to use types in the colloquial "dynamic type" meaning as tags on values, and you also want to talk about generics (a feature that only makes sense for types-as-compile-time-properties) you need to be really careful in your terminology or confusion will abound!

oaiey•5mo ago
PHP afair compiles the textual PHP into some intermediate which is then run. So there is a compilation stage.
noelwelsh•5mo ago
That's my understanding as well, so I don't understand why the introduction is worded as it is.
jlbooker•5mo ago
It's a bit of semantics, sure, but there's a subtle difference. In something like Java, there's a very distinct complication phase, the compilation is successful (type checks pass) and the bytecode is shipped off, and someone else runs that bytecode later. In PHP, you ship the code itself and the compilation phase is essentially the same as runtime. There is no distinct phase where types are pre-checked and analyzed. In PHP, all the syntax and type checking happens during (a phase of) runtime.
noelwelsh•5mo ago
Addition, as I missed the edit window.

I wish they would elaborate on what Really Really Hard(tm) means. From a high-level I believe everything they are concerned with has been researched as part of the work on contract by Robby Findler and collaborators. E.g. https://users.cs.northwestern.edu/~robby/pubs/papers/popl201...

johnisgood•6mo ago
Nay, enough of complexity as it is, for now.
rob74•5mo ago
So, PHP started off as a loosely typed language, then got types... and now they want to implement generics to have more loosely typed code? But as I understand it, types are still optional, so you can still use untyped variables for "generic" code? I'm probably missing something here, is it because of performance concerns? Or the edge case of absolutely wanting strongly typed PHP throughout (except for the part where they want generics)?
purerandomness•5mo ago
Today, the vast majority of commercial PHP projects are developed enforcing the use of strong types by static analyzers like PHPStan in the CI pipeline, and having the strict_types declaration set.

As a community, we've seen enough untyped PHP spaghetti code in the early 2000s and never want to go back there.

actionfromafar•5mo ago
Generics are not equivalent to loose types.
bastawhiz•5mo ago
> they want to implement generics to have more loosely typed code

That's a weird way to think about generics. Any class using generics effectively functions as a version of the class where the types are explicitly written out in all places. Instead of writing out one version of the class for every generic type, you write it out once and say which version you want to use at instantiation. You lose no safety, it's purely cosmetic and quality of life.