First, you can have a type-checker check the currency; that doesn't have to be a runtime error:
Money<Usd> m = …;
There will, of course, be instances where you must handle currency dynamically."MoneyExpr" is a bit more complicated; I find most people usually implement "MoneyBag" intuitively first, so it's odd they left that for third? So, the article gets there, and we "fix" the problems, but it feels roundabout.
The criticism of MoneyBag is bizarre:
> Compared to the Martin Fowler’s design, it remains heavier. It consumes more memory and more CPU
This is apples to oranges? Fowler's design is a Money type; MoneyBag is a different thing; of course it consumes more memory. A Vec<int> consumes more memory than an int, too?
Perhaps the article author isn't comfortable with that Money merely isn't closed over addition. But if you accept that Money isn't closed over addition, then naturally there must be another type in the type system.