How can we define some data type (for example a view layout) such that (1) we can later add new variants (new views) and (2) we can add new behavior (rendering to AppKit in addition to UIKit) without losing type safety or touching the first bit of code? This is known as the Expression Problem. Will Brandon find a way to solve it?
Subclassing solves (1), but we can’t add new rendering logic to a base-class from outside that module. Swift’s enum solves (2), but we can’t add new cases later without modifying the enum. Swift 5’s Non-exhaustive-enums won’t work either. The Final Tagless Interpreter approach solves (1) and (2) taking advantage of Swift’s powerful Self type inside protocols. Data is defined with a protocol, new variants are added with protocol inheritance, and new behavior is added by providing a new protocol instance. Expressions are declared with generic functions and evaluated with identity functions. It’s wild! What’s unique about the Final Tagless approach is the clean separation both between any item and any possible evaluation of those items. This encourages an ecosystem of independent lego-block-like libraries from independent authors that can be glued together in ways neither author anticipated. Brandon believes Final Tagless Interpreters are a hidden gem as they are simple to understand and extremely powerful for solving all sorts of problems in our Swift code!