&gt; we should not be conflating dynamic dispatching code which could be statically resolved from dynamic dispatching code which is necessarily dynamic.<p>This is exactly what I said: most of what people call &quot;dynamic dispatching&quot; is not truly dynamic, and the use of dispatching code is merely an implementation detail.<p>&gt; In Haskell, you do not do this sort of dispatch with typeclasses, but instead use ADTs.<p>Except you can, and this is one way to solve the expression problem in Haskell, ie. by lifting constructors to their own types with pattern matching functions lifted to type classes. At which point we come full circle: most uses of ADTs can also be monomorphized and so are not dynamically dispatched either.<p>Dynamic dispatches then occur only on input at runtime to select the type being instantiated (and so the type class being dispatched into).