Hacker Newsnew | past | comments | ask | show | jobs | submit | glittershark's commentslogin

it looks like there's a recording linked at the end of the post


there are plenty of people with commit bits (me included) who don't reside in Russia, and would (I hope) be pretty alert to the Russian state coercing tazjin (the only committer currently residing in Russia) into introducing some form of backdoor.


The benchmarking harness that the post uses is based on criterion


a 10% drop in performance with bounds checks removed, mind you - so if anything the bounds checks are improving performance.


The more likely explanation is that the test is bunk.

Or maybe the unsafe access acts like volatile in C and disables any optimization/reordering because the compiler thinks it’s accessing a register.


Unsafe accesses do not act that way, they compile to exactly the same code as array accesses in C.

The tests aren't bunk. There are a variety of reasons why the assertions generated by array index checks can be useful for LLVM, and there is also a fair amount of noise in any end to end test like this. The main point is that it clearly isn't a primary bottleneck (which should be pretty obvious in a test that takes 30 ms and performs under 2000 bounds checks).


there's a cheeky link to idris's vector type in the second paragraph: https://www.idris-lang.org/docs/idris2/current/base_docs/doc... which accomplishes just that


We've thought about that, actually! We have an experimental mode where multiple copies of the same query can be created (actually just multiple copies of the leaf node in the dataflow graph, so intermediate state is reused) with different subsets of keys materialized - the idea is then that these separate readers would be run on different regions, so eg the reader in the EU region gets keys for EU users, and the reader in the NA region gets keys for NA users.


the remaining 10% of the 90%-off free lunch is pretty much just eventual consistency - it can occasionally be the case that you write something to the DB, and an immediate subsequent write doesn't see it. That said, there are escape-hatches there (we'll proxy queries that happen inside of a transaction to the upstream mysql/postgresql database, and there's an experimental implementation of opt-in Read-Your-Writes consistency), and I'd wager that the vast majority of "traditional" web applications can tolerate slightly stale reads.

Our official docs also have an aptly-titled: "what's the catch?" section: https://docs.readyset.io/concepts/overview#whats-the-catch


I think it probably falls more into the category of removing a restriction rather than a new feature, but I'm still waiting on HKTs - not for traits (as a former die-hard haskeller, I have been gradually converted to the side of "rust doesn't need a Monad trait") but for data types. There's a design pattern in haskell called "Higher-Kinded-Data"[0] where you parametrize a datatype on a type-constructor, and use that to generically define either partial or total versions of that data type- something like (in rust syntax):

    struct Person<F> {
        pub name: F<String>,
        pub age: F<u32>,
    }
where you can then have `Person<Option>` be a person that may or may not have all fields filled, and `Person<Box>` be a person with all fields definitely filled. This is something I find myself reaching for surprisingly frequently when writing rust, and I feel like it's a missed benefit of implementing higher-kinded types.

[0]: https://reasonablypolymorphic.com/blog/higher-kinded-data/

All that said, I'm really excited to have const generics land! Props to all the amazing work by withoutboats and the entire rust team.


In TS this would be flipped:

    type Person = {
     name: string;
     age: number;
    }

    type SomeFieldsMissing = Partial<Person>;
    type AllFieldsRequired = Required<Person>; // No real change in this case
Where Partial and Required are defined like:

    type Partial<T> = { [P in keyof T]?: T[P] | undefined; }

    type Required<T> = { [P in keyof T]-?: T[P]; }
What would you think of something like this ("mapped types")? They can get fairly powerful: https://www.typescriptlang.org/docs/handbook/2/mapped-types....


that seems like something that would only really work with a type system that's as structural as TS (vs rust, which is very nominal)


What would happen if I wanted only some fields to be required? To borrow from the GP example, something like this:

    struct Person<F> {
        pub name: F<String>,
        pub age: Option<u32>,
    }
With `Person<Box>` still leaving `age` as optional.


You can do it like this:

  type RequiredKeys<O, K extends keyof O> = Omit<O, K> & Required<Pick<O, K>>
  type Person = {
    name?: string
    age?: number
  }
  type RequiredName = RequiredKeys<Person, 'name'>
The opposite (making some of the fields optional, without affecting the rest) would be written like this:

  type OptionalKeys<O, K extends keyof O> = Omit<O, K> & Partial<Pick<O, K>>


Yes, you can do this in typescript, but you can also lie about it in typescript. To do it provably, you would construct a function that accepted the more generic version and then, using type assertions (ie the typescript compiler infers the type from declared runtime behavior), it would return a narrowed type.

If one caller passes our type narrower with {age:F<u32>} then the return value of the function will be narrowed to that type, but a broader criteria can still be specified for the generic instance.


Add an extra generic parameter.

(Also, it shouldn't be Box; you'd want a bog-standard generic newtype for this, not an extra heap allocation.)


yeah, I picked Box mostly as a pedagogical instance of the identity functor that already exists in the stdlib - in the real world you'd definitely want `struct Identity<F>(F)` instead.


Yeah there's going to be tradeoffs either way, the question is how often they come up in the situations the language is designed to target (versus random examples designed to showcase some obscure corner of PLT)... In this case for TS you might craft your own mappings that work like AllButXOptional<Person, 'age'>, or similar. So it's controlled externally versus internally, which who knows if thats better or not. One benefit of the TS approach is that it's a bit more composable... you can imagine things like OptionalIfRequiredInOther<ComplexPerson, SimplePerson>.


That superficially looks horrible. How do you write `Person (Compose Maybe Maybe)`, even, never mind anything more sophisticated?

Edit, for that matter, how do you deal with a `Person f` that includes a `f (Maybe Something)` without confusing "the user didn't specify a `Maybe Something`" with "the user specified a `Maybe Something` with value `Nothing`" (or vice versa)?


I'm not sure what you mean by `Person (Compose Maybe Maybe)`? Is that a person with values you have to unwrap twice to use? That's not really a thing in TS, it either is undefined or isn't. But if you need to shoehorn Haskell into TS for whatever reason I guess you could do something like:

    type Maybe<T> = {hasValue: false} | {hasValue: true, value: T}
    type Shoehorn<T> = { [P in keyof T]-?: Maybe<Maybe<P>> }


> I'm not sure what you mean by `Person (Compose Maybe Maybe)`? Is that a person with values you have to unwrap twice to use?

`Compose Maybe Maybe T` (equivalently `Maybe (Maybe T))`), has N + 2 values (where N in the probably-infinite number of values T has):

. N values consisting of a T

. 2 different values that do not include a T

It's also equivalent (via 1 + (1 + N) = (1 + 1) + N) to `Either Bool T`.

And yes, `Person f` contains values of type `f Whatever`.

> it either is undefined or isn't.

Values are never undefined. They might be defined as a object that's called "undefined", but that is a specific, defined, value. And, apropos of the above, it's a single value, out of the two distinct non-T values being represented. Which is part of why the example at https://news.ycombinator.com/item?id=26277598 looks horrible - it seems like it would confuse the two different non-T values with each other if `Person f` includes a `f (Maybe T)`.

Edit: actually, clarified the previous comment a bit, too.


> > it either is undefined or isn't.

> Values are never undefined.

I am referring to the JS concept of the singleton `undefined`, not an abstract idea of definedness.

Overall I see where you're coming from, but scrambling Haskell and TypeScript syntax is severely impacting legibility.

End of the day Haskell and TS have very different use cases, one is a research language exploring the reaches of type theory, the other is type system bolted onto a dynamic language doing the best it can. Sure there are some concepts that it can't express, but that's entirely missing the point.


I don't know what kind of software you write, but I build the same CRUD app and UI-flavor-of-the-month frontend, over and over.

I have no clue what "N + 2 values (where N in the probably-infinite number of values T has): N values consisting of a T" means and I've done fairly well for myself.

Why does anyone need this to write and deploy CRUD apps and put forms + buttons on stuff?


Parent's Haskell background is leaking, but the idea is "wouldn't it be cool if you could have a value that was either "A box containing a box containing a Person", "A box containing a box containing nothing", or "A box containing nothing""?? How supremely useful and not at all confusing would that be?

I kid, but I admit there is a valid division between coding to explore the consequences logical frameworks and coding to extract money from corporations while providing them a way to keep their orders coming in and accounted for. I'll gladly spend time on both sides of the spectrum, depending on how many drugs are in my system and how much food is in my belly :)


I like and enjoy HKTs in other languages, but don't feel a super strong need for them in Rust. I know some other people differ. It is very unclear when, if ever, Rust will get HKTs proper. GATs cover a lot of the same ground. We'll see :)


Wow, higher-kinded data. I've never heard of that, but it would absolutely be useful. E.g. for converting JSON inputs, where any field might be missing, into a version of the data which definitely has values for all the fields. Or a version of the struct where the values are actually read from a cache/database.


I proposed using it to model lifecycles of entities:

https://github.com/tim-group/higher-kinded-lifecycle/blob/ma...

(in this code, "idea" is a domain concept from the firm i worked for at the time - basically a recommendation to buy a stock, which is 'opened' on a certain date, and 'closed' when it no longer seems like a good recommendation)

My collegues didn't like it, and stuck to using separate types for objects in different stages of the lifecycle!


TypeScript (as you might expect from a lang built for dealing with JS Objects), has really great tooling for this kind of type narrowing these days (including on string template matching now) and I miss it so much now that I’m writing Go.


yes! once you use it you start wanting it everywhere, which is a big part of why I wish I could do it in Rust


This might be of interest to you (this is the second article in the series, and they've been good so far)

https://rustyyato.github.io/type/system,type/families/2021/0...


> where you can then have `Person<Option>` ... This is something I find myself reaching for surprisingly frequently

What's a practical use case for it? It's cool in theory, but I struggle to come up with something that doesn't use at most 2 implementations (just copy the struct then), or some API where the types don't mix and can be generated via a macro instead.


Pretty sure this paper describes what they're doing now: https://research.fb.com/publications/flighttracker-consisten...


I'm not sure if FlightTracker completely replaced the need for the internal consistency inside Tao. You can read about that here: https://www.usenix.org/system/files/conference/atc13/atc13-b...


Not a lawyer (ironically) but afaik there are all sorts of laws governing an attorney-client relationship, and it's possible to implicitly enter into such a relationship by giving something resembling legal advice.


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: