Of course, you will have IO somewhere in a executable where you can handle logging so just separate pure and IO and make sure you have good tests for the pure functions. Also, linting to catch partial functions and dangerous lazy ones (or use an alternative prelude).
Most of this can still be done from IO places where the pure functions collect enough error information bubbling up (e.g. content and line/col of parser errors etc.) to not need ad hoc print statements for debugging.
You lose the ability to log "why" some effect is happening.