6 ms·
I do agree that there are problems where the "maps of facts" approach is better suited than ADTs. I'm not sure if those are the majority of problems we're solvi
by hepta 9y ago
I do agree that there are problems where the "maps of facts" approach is better suited than ADTs. I'm not sure if those are the majority of problems we're solving. You can still do all that in a typed language, using dictionaries. You can be as precise as you want. In some sense you lose that without a type-checker.
I only have my experience (which is about 1/4 of his) to lean on. And I've only had problems when protocols are not well understood by all parties, never the opposite. Talking in the level of ADTs (or some representation that is equally precise) tends to either clear things up, or uncover problems that were not obvious in informal discussion.
- wellpast 9y ago> Talking in the level of ADTs (or some representation that is equally precise) I will argue that ADTs offer no more precision than first-class properties and first-class properties are much more aligned with human beings natural way of thinking. I.e., "name" is semantically strong/precise, I don't need to enslave it to a Person class. I can give a Cat a name, a building a name, etc. ADTs are trying to bundle properties together when those properties should/could have strong enough semantics on their own and be much more "composable" (RH's term) and freer to use.
- hepta 9y agoMaybe we have to dig into the specifics: there's a lot of things that can be done with Name, regardless of where the name belongs, is that what you mean? If so, most typed languages let you say that Person can be a thing with a Name. I don't have Clojure experience so we might be talking past each other here.
- wellpast 9y agoWhat resonates most with me is that traditionally ADTs make the properties second-class citizen to the ADT/class. First-class properties are strong enough semantics and bundling them together in an ADT is almost always introducing coupling and rigidity with no real benefit. Why do we need the Person class? Why do we need to taxonomize like that? The answer is we don't. All the Person class brings to the table is straight-jacketing and a false sense of order and security.
- mopierotti 9y agoI haven't watched the full video, but here are some things that a hypothetical Person class brings to the table that you might be missing: 1) A Person class can guarantee that a Person can not exist unless it is fully specified. E.g. you prevent Persons from being created that don't have a date of birth. 2) A Person class provides a syntactically nice place to put pieces of code that rely on the instance fields. E.g. a function like Person(...).computeAge(DateTime.now) 3) A Person class can be a nice place to put inter-field validations. E.g. Maybe you don't want to allow Persons to be constructed if their last name is the same as their first name 4) A Person class can bring clarity to function signatures that depend on it. Basically resolving the problems that Duck-typing introduces
- tome 9y agoWhat's a "first-class property"?
- wellpast 9y agoclass Person { def age; } There is a second-class "age" property: the only way to specify it or use it is to first declare the ADT/Person class. (In this example, I use a dynamic language; that is, the property can be given any type of value.) Here is the usage of a first-class age property: public boolean isOld(Map<String, Object> entity) { return entity.getAs("age", int.class) > 30; } Note that in this example, age's semantics are independent of any Person/ADT. Now a statically-typed language that would let me define a vocabulary that include "age" and its type independent of an ADT would be supporting first-class properties. I could cheat and do this in a typed language like Java like so: class Age { int val; } // using class to define a property class Entity { Age age; ...and list all other properties here... } But this is absurdly cumbersome and obviously Java isn't conducive to this.
- Bogdanp 9y ago> Note that in this example, age's semantics are independent of any Person/ADT. Now a statically-typed language that would let me define a vocabulary that include "age" and its type independent of an ADT would be supporting first-class properties. What you're referring to is known as row polymorphism or structural typing and it exists in languages such as Elm, Purescript, Scala and Go (and I believe Haskell has these as an extension). For instance, this is valid Scala: def isOld(thing: {def age: Int}): Boolean = thing.age > 30 case class Person(name: String, age: Int) case class Dog(age: Int) println(isOld(Person("Jim", 25)) println(isOld(Dog(31)) And here's Elm: isOld : {age: Int | a} -> Bool isOld thing = thing.age > 30 Debug.log (isOld {name: "Jim", age: 42}) Debug.log (isOld {age: 10})
- wellpast 9y agoThis is pretty cool. The Scala version is a little weird. Why do I need a separate Person and Dog class? Can't a dog have a name as well? Why do I need to declare that upfront or ensure that no other part of code can give a Dog a name? That's the problem with ADTs; there's all this impedance. The Elm version is much better. Except of course I have to upfront at the method signature declare my property requirements -- while that is also a burden, it is a much lesser burden than having ADT/taxonomy of Person, Dog, etc.
- wtetzner 9y ago> I do agree that there are problems where the "maps of facts" approach is better suited than ADTs. I'm not sure if those are the majority of problems we're solving. This also seems like the kind of thing where row-types would allow for statically typed, fully inferred programs that are written in the style Rich is advocating.