4 ms·
Programming is beautiful! I'm writing an authorization expression parser that generates a Validation applicative functor (whose errors form a semi-group, so co
by agentultra 10y ago
Programming is beautiful!
I'm writing an authorization expression parser that generates a Validation applicative functor (whose errors form a semi-group, so cool!). The users will only notice that the error messages when they fail authorization will be descriptive of what they're missing. The developers love it because they get a rich, descriptive language. And it makes me happy because it's actually not a lot of code.
If I had written it the boring way there would probably be more code, be less useful, and I would've tried to find some way to punt the work onto someone else.
Beautiful code is not just a way to check of your *-ility's. It's also inspirational. And being inspired leads to creative solutions which amplify the value you can generate. Sometimes the boring solutions lead to byzantine, institutional code whose intent, purpose, and function remains a mystery.
For me clarity and utility stem not from documentation and mountains of tests. It comes from being succinct, clear, and precise. At least the author and I agree on one point: simplicity is key.
- hawkice 10y ago> I'm writing an authorization expression parser that generates a Validation applicative functor (whose errors form a semi-group, so cool!). It's either the successful result or a list of errors. That's what you're describing here. Boom -- boringified.
- disconcision 10y agohmm yes but what if we construe boringification as decategorification of the n-category of interesting algebraic constructions?
- marcosdumay 10y agoWell, if you do that with the right interface, a "successful result or a list of errors" is a "Validation applicative functor (whose errors form a semi-group)".
- iduy 10y agoSorry I don't understand what you built, but it seems interesting, can you please explain it in plain English.
- agentultra 10y agoSure! The problem I need to solve is to add an authorization system to our stack. Because we need to support a good number of authorization scenarios the system needs to be flexible. So I wrote an expression parser that takes an "authorization expression" in my input language and outputs a function. That function takes the authorization context and either returns a Success value or a list of Failure. The pattern I'm using to generate that function is called a "Validation." It's a kind of applicative functor which is essentially a list of functions we map over. The result is the success value or a semi-group of the failed functions. All my expression parser has to do is generate the "list of functions" to feed into the Validation. This is really cool because now I can write very expressive authorization clauses and it always generates a nice function that either passes or gives the user a nice list of the exact conditions that failed. It's a surprisingly small amount of code for such a handy tool... Which means it's simple in the sense that it's precise and succinct. Savvy? I took some liberties with the definition of what an applicative functor is. If you're interested there are a great number of resources to learn about them and I encourage everyone to read up and try to understand the true definition themselves.
- gandolfinmyhead 10y agosooo :: Foldable b => String -> (a -> Either a b)
- marcosdumay 10y ago> If I had written it the boring way there would probably be more code, be less useful It's the bugs. If you write it the boring way, it will be complex enough to be full of bugs. And it will need to change all the time. And next thing you see is that you are now working full time on improving error messages and can't afford to do anything interesting anymore. Still, that excitement comes from making things less complex. KISS always apply.