hPutStr uses different line endings in different buffering modes on Windows
I haven't tried to repro this so sorry if this is a false positive.
I was looking at what line endings langs/compilers/runtimes print on Win and Linux/osx.
It looks like GHC, on Windows, prints \n in NoBuffering mode, but \r\n in LineBuffering mode.
Code for NoBuffering: https://github.com/ghc/ghc/blob/b57200de601e4ef6827727176611d7192016b8b2/libraries/ghc-internal/src/GHC/IO/Handle/Text.hs#L654
This prints \n regardless of what the handle's line ending is.
When buffered, the same function calls writeBlocks with the handle's line ending passed, which I think will print \r\n in: https://github.com/ghc/ghc/blob/b57200de601e4ef6827727176611d7192016b8b2/libraries/ghc-internal/src/GHC/IO/Handle/Text.hs#L689
Secondly, the expected behavior of what hPutStrLn, readLn and similar "print/write or read with newline" should print or expect for the line endings should be documented. I checked putStrLn, hPutStrLn, and readLn. I don't know what other similar functions exist.
As an example, this is the Rust docs specifying expected line endings in read and write functions:
-
https://doc.rust-lang.org/std/io/trait.BufRead.html#method.read_line (expects
\nregardless of the platform,\rwill be part of the yielded lines) -
https://doc.rust-lang.org/std/macro.writeln.html (writes
\nregardless of the platform)