3 ms·
> I could not understand why most static language required writing so many types that were easy to deduce and why people where saying that not having to write t
by mcphage 6y ago
> I could not understand why most static language required writing so many types that were easy to deduce and why people where saying that not having to write types made dynamic language better.
In Scala, a lot of libraries end up with deduction-only types—ie, types that can only be deduced, because actually typing out the type signature is very long, complicated, and filled with generics-upon-generics. I don’t find that to be a pleasant outcome—if I can’t fill in the type signature myself, trying to understand what the code is going to do ends up that much more complicated. Yet that’s not an uncommon situation.
- The_rationalist 6y agoBut 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?