Capable modules?
I recently came across a blog post by Thomas Leonard entitled Lambda Capabilities. This provides an interesting framing of the well-established security concept of capabilities (broadly, explicit, fine-grained authorisation as opposed to policy-based permission) in terms of functional programming. This essentially boils down to the observation that, if you don’t have global variables (a good idea for a variety of reasons), and stick to pure functions, the formal parameters can serve as capabilities — a function can only access the things that you pass in to it. For example, if I only pass in the htdocs
directory object, the function can’t access files elsewhere1.
The ergonomics of passing every capability a function might use explicitly may sound questionable, but there’s a widely used example: JavaScript’s AMD modules. While decidedly not ticking the “purity” box, they’re strikingly similar in use: each module is a function, taking as parameters all of the other modules it needs.
AMD modules have since been superseded by standardised module
support, and in any case JavaScript’s mutability and abundant built-in global state mean that they’re not an effective capabilities mechanism, but they provide good evidence that the idea is both usable in practice an not unique to functional languages like OCaml and Haskell2.
An even more relevant comparison is with WebAssembly, which does not start with the same global baggage, and has a sandboxing model that explicitly prevents cross-function leaking. A WebAssembly runtime built around this model of capabilities seems like a very interesting proposition.