The C# unions as described are discriminated unions.
The fact that they flatten a union of optional types into an optional union of the corresponding non-optional types is indeed a weird feature, which I do not like, because I think that a union must preserve the structural hierarchy of the united types, e.g. a union of unions must be different from a union of all types included in the component unions, and the same for a union of optional types, where an optional type is equivalent with a union between the void/null type and the non-optional type, but this C# behavior still does not make the C# unions anything else but discriminated unions, even if with a peculiar feature.
> that a union must preserve the structural hierarchy of the united types, e.g. a union of unions must be different from a union of all types included in the component unions, and the same for a union of optional types, where an optional type is equivalent with a union between the void/null type and the non-optional type
This is exactly the difference between simple union types and discriminated unions. This c# feature is what typescript has, not what Haskell/java/f#, etc.
The word "discriminated" by itself does not specify this property.
"Discriminated" just means that at run time you can discriminate the values of a union type by their current type, so you can use them correctly in expressions that expect one of the component types.
I agree that the right implementation of discriminated types is that mentioned by you and which is that of many important programming languages, but even if I disapprove of this property that the C# unions have, which in my opinion may lead to unexpected behavior that can cause subtle bugs, the C# unions are still discriminated unions, where you can discriminate the current type at run-time, with a "switch".
In my opinion, one should avoid this weird behavior of C#, by always defining only unions of non-optional types. Where needed, one should then define an optional type having as base a union type. Then these unions will behave like the discriminated unions of other languages.
Whether you use or not this policy, there are types that the C# unions cannot express, but if you use this policy, at least the limitations become explicit.
It'll be interesting to see how the timing is enforced. Can you just set up your own NTP server to fool your phone into thinking it's really the future (and not just you adjusting your phone's clock manually). Will Google run a clock that you have to get a timestamp from (would it be easy to setup your own MITM proxy to get around this?). If the time somehow jumped backwards, would you lose the ability to install apps? Can google remotely disable this after it's already enabled (I think yes)?
I think it would be a bad idea to require an internet connection (for one thing, you might want to write your own app that does not require a internet connection); but, even if it doesn't, would not mean you can set the clock to avoid the delay, because it could be made to reset the delay if the clock is set.
They're not doing so here, but shipping a wasm-compiled binary with npm that uses node's WASI API is a really easy way to ship a cross-platform CLI utility. Just needs ~20 lines of JS wrapping it to set up the args and file system.
There's no such thing as a truly "cross-platform" build. Depending on what you use, you might have to target specific combinations of OS and processor architecture. That's actually why WASM (though they went with WASI) is a better choice; especially for libraries, since anyone can drop it into their environment without worrying about compatibility.
I think GP's point is that instead of having 3 target-specific rust-built binaries, they have 3 target-specific node binaries running rust-built wasm plus wrapper code.
That's essentially correct. Extraction is a term in roqc. A rocq program contains both a computational part, and proofs about that computation, all mixed together in the type system. Extraction is the automated process of discarding the proofs and writing out the computational component to a more conventional (and probably more efficient) programming language.
The original extractor was to ocaml, and this is a new extractor to c++.