This version is more composable and also simpler at the expense of being more explicit and more verbose.
This patch provides rationale for the framework, implementation and unit tests but the functions themselves are still using the previous version. The change in implementation will come in a follow up patch.
Maybe give a better error message: "a loop of size 1 does not need tail, use 'Loop' instead" ?