It seems like there's a combinatorial explosion of possible overloads in Swift, whereas if you implement a function with the same ergonomics in Haskell (e.g. a printf-like function), the only thing the compiler has to do is ask "Does type X have an implementation for typeclass Show? Yes? Done."
Essentially Haskell solved this overload inference problem in the same way that iterators solve the M*N problem for basic algorithms: convert all these disparate types to a single type, and run your algorithm on that.
let f0 = fun x -> (x, x) in
let f1 = fun y -> f0(f0 y) in
let f2 = fun y -> f1(f1 y) in
let f3 = fun y -> f2(f2 y) in
let f4 = fun y -> f3(f3 y) in
let f5 = fun y -> f4(f4 y) in
f5 (fun z -> z)
Lifted from https://dl.acm.org/doi/pdf/10.1145/96709.96748 via Pierce, Types And Programming Languages.It's still very fast for "normal size" types. That reduced version compiles in 151 milliseconds.
I almost never bother putting types in Haskell, unless I want to guarantee some constraint, in which case I typically use typeclasses. Maybe I'm just weird but I don't think so. One of the very few things I actually like about Haskell is how good the type inference is.
HM isn't bidirectional in the special case, so probably the features they added vs the top level universal quantifier type that has pathological low time complexity.