Hacker News new | ask | show | jobs
by saityi 2310 days ago
Paul Snively (the author of the linked reddit post) also gave a great talk entitled 'Typed FP on the Job - Why Bother?' at LambdaConf a couple years back, that spoke strongly to me:

https://www.youtube.com/watch?v=8_HsFrXhZlA

> And now you can do the most important thing you can do with any piece of code... stop thinking about it! Go home! Pet the cat! Watch House with the wife! ... I love Friday deployments ... you know why? Because I know what my code is going to do before it runs!

2 comments

I'm so glad that struck you! I think a lot of organizations talk about "work/life balance" without really doing anything concrete to make that possible, and I certainly appreciate the irony that this purportedly very abstract, theoretical approach to writing software is, head and shoulders, the most impactful thing to my quality of professional life.
Interesting talk, but does that retry logic really provide me with more confidence about its correctness than equivalent impure code?
Thanks, and good question.

I deliberately didn't go into the specifics about the various typeclasses at play and their laws, and how those are tested. Part of that is just for reasons of time, but the more salient reason is that I wanted to show how those of us who do purely functional programming do it in practice. So if you watched the presentation, you saw that most of my thinking was about "OK, how do I elaborate from the most trivial transformation (do nothing at all) to the one I really want?" And that proceeds compositionally: I transform this value to that value. OK, does that value have the right type? No? What do I need to do to ensure that it does? And the transformation steps have some important properties, like their scope being entirely local. I really tried to emphasize this at the end with `attemptRepeatedly`: my description of each line of the whopping three lines is exhaustive. When I say there's no point in writing a test for it, I mean that literally. There certainly are typeclasses at play, and I briefly talk about the `Catchable` typeclass, and show the ScalaDoc for it, which documents an important law: the relationship between catching ambient exceptions and the algebra provided by `Catchable`. I rely on the other typeclasses and other laws in a similar fashion.

The other thing I think is pretty important is the part where I say "Let's look at cases," because the point there is that I can reason about the code by reasoning about the shape of the data it's manipulating. So if a `step` is an `attempt` of `p` that, if successful, `kill`s the retry `schedule` or, if unsuccessful, logs the exception, I'm still dealing with a `Process` of one element (by assumption that `p` will emit one element). Then `retries` will be a `Process` of 0 to infinity elements, because we put no constraints on `schedule`. So `(step ++ retries)` will be one or more elements, and because `step` `kill`s `schedule` on success, because `retries` is derived from `schedule`, `retries` is also `kill`ed. So `(step ++ retries)` is a `Process` that will emit one or more elements, with the last element being the first successful one, or the last failed element if none of the `retries` succeeds, so we take `last`. Then we just `fold` the failure or value back into a single effect, and we're done.

As I discuss in the presentation, there certainly are questions. What happens if the `schedule` is empty? What happens if the `schedule` is infinite? An attendee in Q & A asked a really good question: was I sure `retries` would wait before the first retry, or was the semantics "try, then wait?" (It really is the former, but that wasn't clear from my recorded REPL session.)

Of course, this isn't very impressive for a three-line example, although I think it's pretty striking that it only takes three lines, each of which can be completely reasoned about independently, to achieve a pretty significant operational goal. The point, though, is we can build entire systems this way, and in fact `attemptRepeatedly` is part of a distributed monitoring system I worked on at Intel Media/Verizon Labs, which is written entirely in this way apart from the monitoring types themselves, which present an imperative API for familiarity's sake (and which we later came to regret).

I hope this helps!