samprotas
My guess is that’s what’s happening here.
https://hackage.haskell.org/package/async
The package description at the top of the link touches on the motivations which basically mirror this article.
I’ve personally never reached for the built in forkIO. withAsync or it’s helpers like mapConcurrently are always equally capable, easier to use, and with none of the foot guns.
For the rare case of lift-and-shift-ing for a system upgrade I felt morally okay about eventually pulling the plug on them, but I'd hesitate to design a system that relied on well-behaved DNS clients if I had a reasonable alternative.
Java/Go/C++ are perfectly capable of parsing a "type" key and conditionally parsing different shaped data. If you make a programming mistake here, you'll get a parse error (bad, but not a security problem). The pushback seems to be that a Java/Go/C++ implementation adds LOCS and won't gain much by doing this extra step so lets make the protocol itself match match their (less precise) data representation.
FWIW there is work towards improving Java in this regard: https://cr.openjdk.java.net/~briangoetz/amber/pattern-match....
That said, I think the constructive suggestion would be: "add a type tag to all objects in a union" (something suggested elsewhere in this thread).
Their "handles" can still claim "just a string" to save bandwidth in the common case, arrays can still represent "many things" and objects require "type" to be dis-ambiguous.
Most of the comments below don't mention the (real and important, but easily solvable) issue you've brought up however. They primarily fall into one of two buckets:
- It's hard to work with data shaped like this in my language (ex: java/go)
- It's hard to deserialize data shaped like this into my language that has no tagged unions (ex: java/go)
My biggest counterpoint to all of these complaints is: The fact that your language of choice cannot represent the concept of "one of these things" doesn't change the fact that this accurately describes reality sometimes.
A protocol with mutually exclusive keys (or really anything) by convention is strictly more bug-prone than a protocol with an object that is correct by construction.
Yes, many mainstream languages have near-zero support for Tagged/Discriminated Unions or Enums with Associated Data or Algebraic Data Types (pick your favorite name for the same concept). This is a limitation of those languages, which should not force a language-agnostic protocol to adopt the lowest common denominator of expressiveness.
Consider the problem they're avoiding of mutually exclusive keys in a struct/object. What do you do if you receive more than one? Is that behavior undefined? If it is defined, how sure are you that the implementation your package manager installed for you doesn't just pick one key arbitrarily in the name of "developer friendliness" leading to security bugs? This seems like a much more bug-ridden problem to solve than having to write verbose type/switching golang/java.
Implementing more verbose deserialization code in languages with no support for Tagged Unions seems like a small price to pay for making a protocol that leaves no room for undefined behavior.
To be clear, _many_ statically typed languages have perfect support for this concept (Rust/Swift/Scala/Haskell, to name a few).
This article has some nice specific examples of "Simple" APIs that push the complexity onto the programmer. https://fasterthanli.me/blog/2020/i-want-off-mr-golangs-wild...
Another common example I've seen cited is the need for Go code generation tools in the community (lack of generics pushing the complexity to external tools).
.
The parens around it are Haskell notation for using an operator in prefix position, which is often how operators are displayed in a “standalone” context such as this.FWIW they have this post from almost 3 years ago about adding Haskell to their stack. I'm guessing the time for your prediction has come and gone.
On the other hand, I find it quite encouraging that Haskell was barely mentioned. It seems they viewed the risk as "changing the projects language" rather than "using a non industry standard language".
So maybe my concern is more a verboseness issue rather than expressiveness.
That said, it would be nice if there was some commentary on whether an implementation like Swift’s was considered and ruled out for some reason. As it reads now, I stand by my original comment that this restriction seems a bit arbitrary.
Composing contracts is a slightly more verbose fix for allowing multiple contracts for a given type (just make a composed contract and specify that).
Using composed contracts, allowed:
func Foo(type T PrintStringer)(s T) {...}
I read this as, while a function can have multiple type parameters, only one contract can be specified in total.Not allowed (function uses "setter" and "stringer"):
func Bar(type B setter, S stringer)(box B, item S) {...}
Maybe I'm misunderstanding though.In other languages with parametric polymorphism, the real re-use comes in by allowing functions like Bar to be used for any combination of "constraint implementing" types.
Anyone else find this limitation a bit disappointing? Seems like a somewhat arbitrary restriction that limits the usefulness of this feature. I hope it doesn't take another 10 years for this to be changed...
Everyone seems to agree successful companies have started in SV and outside of SV, and that there’s a lopsided distribution. No one has spent much time on whether the location is the cause of or just correlated with success. I get that this is hard to determine, but maybe people should speak in less absolutes? The article is one persons decision making process, explained for the benefit of others. I don’t think it’s claiming to be The One Truth.
Disclaimer: I worked for the author in Philly previously.
My theory was, when they switched from LotusNotes to Outlook, they never ported over years of worth of experience encoded in user permissions. At least that fits well with the warning people always give about re-writing legacy software....