You're absolutely correct however Haskell has a couple of function that let you circumvent it's normal evaluation rules which you can see in https://hackage.haskell.org/package/base-4.12.0.0/docs/Syste....
These are sometimes useful for optimization but in an unfortunate bit of history, some developers decided to use these to "simulate" Haskell's lazy semantics for side-effecting I/O operations, the so-called "lazy I/O".
Fortunately this is just a few functions in the standard library which you can simply avoid and serious Haskell codebases should use a linter to prevent people from calling them.