One thing I can think of is that it can guarantee that the string will be printed as a unit, without any other trace messages inside. Indeed, the experiment seems to confirm this:
Prelude Debug.Trace System.IO> traceIO $ "1" ++ trace "2" "3" 2 13 Prelude Debug.Trace System.IO> hPutStrLn stderr $ "1" ++ trace "2" "3" 12 3
Another difference is that characters that cannot be safely printed to stderr seem to be deleted:
Prelude Debug.Trace System.IO> hPutStrLn stderr "\9731" *** Exception: <stderr>: hPutChar: invalid argument (invalid character) Prelude Debug.Trace System.IO> traceIO "\9731" Prelude Debug.Trace System.IO>
As @dfeuer reminds me, none of these features are writable in Haskell. Thus, the decisive factor is probably the following: debugBelch already a predefined function of C, it is used everywhere in the GHC runtime system, which is written in C and C--, and not in Haskell.
source share