4 ms·
But why the complexity? Most libraries should have "simple" types.
by The_rationalist 6y ago
But why the complexity?
Most libraries should have "simple" types.
- mcphage 6y agoThey should, but when the types are all inferred, it’s easier to hide that complexity.
- lmm 6y agoThey mostly do. The cases where you get complex types is where you are using dependent typing. For example, imagine you wanted to write an "update" method. So we have this datatype: data Address(line1: String, line2: String, postcode: String) data User(name: String, address: Address, phoneNumber: String) And here's an example of what "update" should do, in JSON: // Argument 1 { "name": "Bob", "address": { "line1": "123 Fake Street", "line2": "Beverly Hills", "postcode": "90210" }, "phoneNumber": "555-555-5555" } // Argument 2 { "address": { "line1": "377 Fake Street" }, "phoneNumber": "555-555-4444" } // Result { "name": "Bob", "address": { "line1": "377 Fake Street", "line2": "Beverly Hills", "postcode": "90210" }, "phoneNumber": "555-555-4444" } This kind of function is the kind of thing that keeps people using dynamic languages. It's easy, and obvious, what it should do, and what its type signature is, but in most typed languages you can't write it without constructing a whole parallel hierarchy of datatypes by hand. Scala is one of about 3 languages where you can actually write this in a nice way and it will be correctly typed. But the type you get will be: (User, Field[Label['name], Option[String]] :: Field[Label['address], Option[Field[Label['line1], Option[String]] :: Field[Label['line2], Option[String]] :: Field[Label['postcode], Option[String]] :: HNil]] :: Field[Label['phoneNumber], Option[String]] :: HNil) => User And until recently it was even worse than that because the compiler didn't know to print the "::" types as infix. Now with first-class record support in the compiler you could improve this a little bit, but fundamentally there's not really any better way to write that type. Maybe if the language had first-class support for dependent types like Idris you could write ti as `(User, UpdateTo(User)) => User` or something, but the reader would still need a way to find out what `UpdateTo(User)` was concretely. So what do you do?