8 ms·
"Maybe Not" by Rich Hickey: https://www.youtube.com/watch?v=YR5WdGrpoug https://www.youtube.com/watch?v=YR5WdGrpoug Another excellent talk by the creator of Cl
by ttiurani 8y ago
"Maybe Not" by Rich Hickey: https://www.youtube.com/watch?v=YR5WdGrpoug https://www.youtube.com/watch?v=YR5WdGrpoug
Another excellent talk by the creator of Clojure, and like the previous ones, relevant for all programmers.
- reikonomusha 8y agoI don’t like Rich’s appeal to human intuition and the physical world as justification for not using—and even disparaging—mathematical structures. His quote from memory was something like “There’s no such thing as a Maybe Sheep,” and that was aggravating to listen to. He then gives the simplest possible examples, and fails to convince me that his approach scales to the real world. At some point he starts talking about what a “person” is and what an “address” is and, somewhat in jest, he says something like “I know I know addresses are difficult this is just a simple example.” It’s precisely the difficult case that I want to see his “intuitive” view of programming actually work out. Rich is a good speaker but I don’t find the line he toes to be agreeable.
- zengid 8y agoHe's a genius but I think he's getting bitter about how people are happily sticking with static strongly typed languages. At the end of the day he's trying to sell people on using Clojure, so of course he's going to rip on other languages.
- maxhallinan 8y agoI thought this was one of the notably bad talks this year. The whole premise that a function of Maybe a should be a function of a without an API change is neither intuitive to me nor really justified by Hickey. Different things are different. It's sad to see someone build such a wall around himself when faced by something (type theory) that he doesn't understand.
- chubot 8y agoAre you sure that he doesn't understand it, or is it possible that you haven't worked with the same scale of systems he has? Here's my response to his talk, which I found insightful: https://lobste.rs/s/zdvg9y/maybe_not_rich_hickey#c_povjwe https://lobste.rs/s/zdvg9y/maybe_not_rich_hickey#c_povjwe Also, I think your comment suffers from the problem here, where you invoke "type theory" without any elaboration: https://lobste.rs/s/zdvg9y/maybe_not_rich_hickey#c_ioeyob https://lobste.rs/s/zdvg9y/maybe_not_rich_hickey#c_ioeyob Rich has taken the time to explain his thoughts very carefully, and his clear about what his experience is, and domains he is talking about. Whereas I see a lot of vague objections without specifics and that aren't backed up by experience.
- joshuamorton 8y agoBut protos and Haskell's type system solve different problems. Perhaps, maybe, public apis like protos shouldn't encode requiredness of any piece of data (I actually fully agree with this). But that says nothing about whether or not my private/internal method to act on a proto should care. Another way of putting this is that requiredness ahiuslnt be defined across clients (as in a proto), but defining it within a context makes a lot of sense, and maybe/optional constructs can do that. Or iow, other peopleay use your schema in interested and unexpected ways. Don't be overly controlling. Your code on the other hand is yours, and controlling it makes more sense. So the arguments that rely on proto-stuff don't really convince me. (I work at Google with protos that still have required members).
- chubot 8y ago> But protos and Haskell's type system solve different problems. That's pretty much my point. Hickey is very clear what domains he's talking about, which are similar to the domains that protos are used in -- long-lived, "open world" information systems with many pieces of code operating on the same data. People saying "Rich Hickey doesn't understand type systems" are missing the point. He's making a specific argument backed up by experience, and they are making a vague one. I don't want to mischaracterize anyone, but often I see nothing more than "always use the strictest types possible because it catches bugs", which is naive. I agree with your statement about private/internal methods. I would also say that is the "easy" problem. You can change those types whenever you want, so you don't really have to worry about modelling it incorrectly. What Hickey is talking about is situations where you're interfacing with systems you don't control, and you can't upgrade everything at once.
- joshlemer 8y ago>that a function of Maybe a should be a function of a without an API change is neither intuitive to me nor really justified by Hickey He spent many minutes motivating it. If you support some functionality to a client (as a library, or a service, or more abstractly), and then later want to relax the constraints that you require from those clients, this should be an acceptable change that they shouldn't have to worry about / be broken by. Like if all of a sudden some REST api no longer requires a specific HTTP header to be present in requests, then this change shouldn't break clients that have been including that formerly-required header all along. Similarly, if you provide something to clients, and you add functionality to provide a response in all circumstances, not just some, then this should not break clients either. This clearly is not true of `Maybe` / `Option[T]` and I think it's a pretty fair critique. Maybe we should be using Union types in these situations instead.
- patrec 8y agoHis argument for spurious API breakage is strictly logically correct, but seems practically dubious to me. When have you ever had to unnecessarily break API compatibility because something you thought was an Option[T] result turned out to be really a T, always? Maybe I'm wrong and someone will post some convincing examples, but I currently don't see this as a problem that needs solving. Union Types don't compose straightforwardly because they flatten; maybe this is desirable in some cases but the rationale in Hickey's talk leaves me unconvinced. The only practical use case for union types I'm aware of is smoother interfacing to dynamically typed APIs; any nice examples for something beyond that?
- IshKebab 8y agoI think you're kind of both agreeing. It would be nice if Maybe did work like he suggested, but in practice it's not that big a deal.
- gavinpc 8y ago> When have you ever had to unnecessarily break API compatibility because something you thought was an Option[T] result turned out to be really a T, always? That would be a breaking change. And should be, if you're into that sort of thing. The objection is to the opposite case: What was a T is now an Option[T]. I don't know Scala specifically, but that's a breaking change in every typechecked language I know. Rich is arguing that it shouldn't be. But it could be possible even in typed languages through union types. For example, you can do this in TypeScript by changing T to T | undefined, which is a superset of T.
- agentultra 8y agoI agree. Further his exposition on `Either a b` was built on a lack of understanding of BiFunctors. The icing on the cake was his description of his own planned type theory. What he described was, as I could decipher from his completely ignorant ravings, a row-based polymorphic type system. However he passes off his insights as novel rather than acknowledging (or leveraging) the decades of research that have gone into type theory to describe the very system he is trying to build. Worse, he continued to implore his audience to spread FUD about type theory, claiming several times, "it is wrong!"
- amelius 8y agoWell, in his defense, type theory is supposed to make software engineering simpler, not more difficult. So if even he doesn't understand it, then how can we expect a random programmer to?
- StreamBright 8y agoWell software engineering is the only engineering field that produces half baked unreliable crappy solutions continuously. Other fields cannot afford such attitude towards products. I think a simple (inferred) type system is pretty useful to increase correctness and it helps you to increase reliability (even though it does not avoid all of the mistakes you can make in software).
- gnuvince 8y agoThe sad thing is that Rich Hickey had some very good videos when Clojure was a new thing back in 2008–2009. Unfortunately, I've disagreed vehemently with most of his talks since then. In this case, it's completely illogical that a function `Maybe a -> b` should be callable as if it were a function `a -> b`. Do you want to know how I know? Because it would be just as illogical to allow a function `Vec a -> b` to be called as `a -> b`. And Rich must agree because Clojure itself does not support that! I've learned that videos of his talks are just not worth my time.
- owl57 8y agoBecause it would be just as illogical to allow a function `Vec a -> b` to be called as `a -> b`. And Rich must agree because Clojure itself does not support that! Maybe Clojure's standard library just isn't that focused on vectors? Python stdlib doesn't support this as well, but NumPy does.
- nadagast 8y agoWhy is it illogical to say that a Maybe a -> b should be callable as if it were a -> b? His point is that Maybe a should be composed of all the values of a, plus one more value, nil. A value of type a is a member of the set (nil + a). Why should having a more specific value reduce the things you can do with it? It breaks composition, fundamentally. It's like saying (+) works on integers, but not on 3. I'm saying this someone who really enjoys type systems, including haskell.
- joel_ms 8y ago> Why is it illogical to say that a Maybe a -> b should be callable as if it were a -> b? Fundamentally because it would require you to conjure up a value of type b from nowhere when the Maybe a is Nothing. If we view the function type as implication this would not be valid logically without some way of introducing that value of type b. You could imagine some function from Nothing -> b that could rescue us. But since it only handles one case of the Maybe type, it is partial (meaning it could give undefined as an answer). There is basically two total functions that we could change it to: * Maybe a -> b in which case we are back where we started. * Unit -> b which essentially is just b, which can be summed up as meaning we need some kind of default value to be available at all times. So to be able to call Maybe a -> b as a -> b you would need some default value available at all the call sites for a -> b Now this is only "illogical" because we don't postulate a value of type b to be used as this default. > It's like saying (+) works on integers, but not on 3 No, it's like saying (+) must work on all integers AND a special value nil that is not like any other integers, but somehow included in them and all other data types. We can't do anything with this nil value since it doesn't carry any data, so in the case of (+) we would essentially have to treat it as an identity element. This is good though, since (+) has 0 as an identity element, so we can just treat nil as a 0 when we encounter (+). However, when we want to define multiplication we still need to treat nil as an identity element (since it still doesnt carry any data), except the identity element for multiplication is 1. This would be repeated for every new function that deals with integers. So by mashing together Maybe and Integer we have managed to get a frankenstein data type with an extra element nil which sometimes means 0 and sometimes means 1. Why not just decompose them into Maybe and Integer and supply the default argument with a simple convertion function like fromMaybe? (FWIW, I actually agree with Hickey that using Maybe in api design is problematic and I've encountered what he's talking about. But while that might be an argument for where he wants to take Clojure, it's not an argument for dismissing type theory the way he does.)
- olodus 8y agoWas about to suggest this myself. I see a few that didn't like this and I can see why, but I thought it was interesting to listen too. Always interesting to hear someone knowledgeable argue for something you don't think you agree with. It is also interesting since Rich is in the quite unique position of handling a functional language with dynamic types (a dying breed in the functional space imo). I don't think Rich fully convinced me to change my mind, but he made me think about when and why Maybe is needed.
- sifoobar 8y agoDying breed based on what? They're different compromises, there is nothing inherently superior about static types. It's more popular right now, because we're very much into rules at the moment; but I have a feeling that's peaking. Typically, you need to move back and forth a number of times before it clicks. So you have all these people on the net fighting over which end of the spectrum is the Right one, and next month they're on opposite sides. They're tools, hammers, screw drivers whatever; it doesn't make any kind of sense to identify with them. Unless your goal is to be a tool, I guess.
- nickpsecurity 8y agoThere is one advantage of formal specs in general that static types inherent: they can enforce a correctness policy on a design that works for all inputs with no runtime overhead. SPARK Ada eliminating entire classes of errors with mostly-automated analysis is one example. Rust blocking temporal and some concurrency errors without GC is another. I'll note they're both hard to eliminate with testing, too. With that, comes the next benefit: less debugging and lower maintenance costs. It has to be balanced against annotation costs. Most projects claimed to come out ahead if it was just safety rather than full correctness. You can also generate tests and runtime checks from specs to get those benefits. So, for high reliability with lower maintenance, there's definitely an advantage to knocking out entire classes of error. That leads to last advantage Ill mention: ability to warranty (market) and certify (regulators) your code free of those defects [if the checker worked]. The checkers are also tiny on some systems. Rarely fail. Inspires extra confidence.
- slifin 8y agoFundamentally changed how I think about modelling data
- AlexCoventry 8y agoThe second half, about his work on spec, is great.
- noxecanexx 8y agoI actually went ahead to learn haskell after one of his recent talks(my motivation was the vehement rejection from the haskell community..on reddit mostly) I haven't turned back since then. It's either he doesn't really understand how types are used or he's intentionally "bad-mouthing" types(which I don't think he's doing)
- bfung 8y agoAfter having code reviewed a lot of Haskell code and managing library dependencies, his talk makes a TON of sense. Some refactorings of code are basically just relaxation of requirements or tightening of return values - and Maybe is littered everywhere / changed everywhere. It just makes the the code hard to read and a lot of busy work - but to no real value. This is the same in Java code. Too many Optional<MyActualClass> / Nullable everywhere. Unit tests littered everywhere to deal with Optionals. But no real functionality change or new information for future maintainers. Just extra cruft. spec seems to be work picked up where Optional / Maybe has left off.
- deleted 8y ago[deleted]
- geokon 8y agoAre the things he illustrates already implemented in Clojure? I'm kinda new to Clojure and I see there is deps.edn and there is clojure.spec, but have they come together into the system he describes? Or is that still "in the works"? I was left a little vague on how it'd work in the end. I guess your program would specify what spec/input-output it expects from a library's API and then the library git history is traversed till you hit the last "version"/hash that matches the spec you require. Then we can just get rid of version numbers entirely and I guess you would just get a warning when a library made a breaking change and your dependency is stuck on an old version/hash in the git tree Am I understanding that right? I get that the new way of development he describes would prevent breaking changes entirely (though it honestly sounds messy with lots of legacy stuff floating around)