Live data from Hacker News

Practical introduction to algebraic datatypes (ADTs) in TypeScript

medium.com

11–20 of 23 posts

Re: Practical introduction to algebraic datatypes (ADTs) in TypeScript

#11

I think this article makes the "sum" and "product" terms out to be very complicated, when in fact it's quite simple. If we have two enums enum Bool { True, False } enum Status { Waiting, Successful, Failed } We can combine them into a product type, like a tuple, or a sum type, like a union. type Product = (Bool, Status) type Sum = Bool | Status Now, we ask ourselves, what are the valid values of type Product? (True,…

First I've heard of exponential type... to make sure I get it, you're saying there are 2^3 possible functions which take a status and return a bool? So if the enum inputs are success, wait, fail, you'd have

Fff

Tff

Ftf

Fft

Ttf

Tft

Ftt

Ttt

All as possible implementations of that function. Neat...

Re: Practical introduction to algebraic datatypes (ADTs) in TypeScript

#12

I think this article makes the "sum" and "product" terms out to be very complicated, when in fact it's quite simple. If we have two enums enum Bool { True, False } enum Status { Waiting, Successful, Failed } We can combine them into a product type, like a tuple, or a sum type, like a union. type Product = (Bool, Status) type Sum = Bool | Status Now, we ask ourselves, what are the valid values of type Product? (True,…

This is a great explanation for its length, thanks!

Re: Practical introduction to algebraic datatypes (ADTs) in TypeScript

#14
post #6

Earlier quoted context omitted.

The Sum is called Union in the TypeScript docs, as it narrows the valid values to the overlapping elements. In the switch statement it becomes a Sum value (as shown in the article). In ReScript (shown as well, which uses OCaml under the hood) the syntax is that of a Variant, in which each element is a different nominal type.

Good point. For example, type NotAProduct = Bool | Bool only has 2 values, not 4. For a real product type, we need type Product = {tag: "Left", value: Bool} | {tag: "Right", value: Bool} which has the requisite 4 values.

This is also called a "discriminated union", with "tag" being the discriminator here.

Re: Practical introduction to algebraic datatypes (ADTs) in TypeScript

#15

The switch case is still a bit redundant and inelegant, particularly considering how out of place switch case syntax feels in a Javascript codebase in general. Early returns are the way to go.

Although I don't mind switch statements, I was thinking similarly about using early returns instead. But this is where switch/match expressions like in Rust or C# would really shine; it's too bad JavaScript/Typescript doesn't support them though.

Re: Practical introduction to algebraic datatypes (ADTs) in TypeScript

#16

The switch case is still a bit redundant and inelegant, particularly considering how out of place switch case syntax feels in a Javascript codebase in general. Early returns are the way to go.

The point of the switch-case is to mimic pattern matching and TS is smart enough tell you whether you handled all cases.

Would you prefer that it's a if-elseif-else based structure instead? I guess that would work too but I feel like it could be easier to write it in a way where you accidentally forget to handle some case (since your else / last return is a potential catch-all).

I personally don't mind switch-case because I'm so accustomed to it in ReasonML/ReScript already.

Re: Practical introduction to algebraic datatypes (ADTs) in TypeScript

#18
post #6

Earlier quoted context omitted.

The Sum is called Union in the TypeScript docs, as it narrows the valid values to the overlapping elements. In the switch statement it becomes a Sum value (as shown in the article). In ReScript (shown as well, which uses OCaml under the hood) the syntax is that of a Variant, in which each element is a different nominal type.

Good point. For example, type NotAProduct = Bool | Bool only has 2 values, not 4. For a real product type, we need type Product = {tag: "Left", value: Bool} | {tag: "Right", value: Bool} which has the requisite 4 values.

So to replicate a Rust enum, C tagged union, or C++ std::variant containing one byte for the type and the rest of the object inline, JavaScript needs a boxed object wrapping a string and the actual object contained inside? And the engine can't optimize away the boxed object into an inline value type because it could have multiple aliasing references in multiple locations? Boxing-based languages make me sad.

Re: Practical introduction to algebraic datatypes (ADTs) in TypeScript

#19
ADTs like the one described here for remote data is a good start, but I haven’t yet found a good way to compose multiple pieces of data that is in potentially different states.

We use another class based concept on top at work where you can compose multiple pieces of remote data together, but it really only works well for the happy path.

Re: Practical introduction to algebraic datatypes (ADTs) in TypeScript

#20

I think this article makes the "sum" and "product" terms out to be very complicated, when in fact it's quite simple. If we have two enums enum Bool { True, False } enum Status { Waiting, Successful, Failed } We can combine them into a product type, like a tuple, or a sum type, like a union. type Product = (Bool, Status) type Sum = Bool | Status Now, we ask ourselves, what are the valid values of type Product? (True,…

This helps handle IO in pure functional languages because? Is it because functions can have more than 1 type?
Post reply on HN