When running the following code
do line <- getLine
putStrLn line
or,
getLine >>= putStrLn
And, after
getLine >>= putStrLn
entering
µ
one encounters this output:
⠀
Now, I already tried chcp 65001
beforehand, which doesn't work, and the encoding of stdin
is utf8
.
An examination without putStrLn
shows:
getLine
µ
'\NIL'
My environment:
Windows 10 Version 10.0.17134 Build 17134
Lenovo ideapad 510-15IKB
BIOS Version LENOVO 3JCN30WW
GHCi v 8.2.2
How can this be solved?
EDIT: Specifically, the following sequence of actions causes this:
- Open
cmd
- Type
chcp 65001
- Type
ghci
- Type
getLine >>= putStrLn
- Type
µ
However, the following does not:
- Search for
ghci
- Open
ghci.exe
at%PROGRAMS%\Haskell Platform\8.2.2\bin
- Repeat 4-5.
NOTE: %PROGRAMS%
is not a real environment variable.
EDIT: As requested, the output of GHC.IO.Encoding.getLocaleEncoding
:
UTF-8
Also, the output of System.IO.hGetEncoding stdin
:
Just UTF-8
(when using chcp 65001
)
EDIT: The character is U+00B5. I am using a German keyboard, system locale Germany, language setting English, Keyboard language ENG with German layout.
Console input/output is utterly broken on Windows and has been for some time now. Here is the top ticket that tracks all the issues related to IO on Windows: https://ghc.haskell.org/trac/ghc/ticket/11394
I believe, these two tickets describe best the behavior that you are experiencing:
The only work around right now is to manually use Windows API for dealing console output/input, which is a pain of its own.
EDIT
So, just for the hell of it I decided to endure some of that pain. :)
Here is the output of the code below:
This is by no means a fully correct or a safe solution, but it does work:
EDIT 2
@dfeuer asked me to list things that are unsafe, incorrect or incomplete with that answer. I only really code on Linux, so I am not a Windows programmer, but here are the things that pop into my mind that would need to be changed before that code could be used in a real program:
GetConsoleMode
API call.BOOL
, and whenever it's not useGetLastError
to report the error back to the user.hwGetStrN
can only handlen
characters, so recursive call would be required in order to get behavior similar tohGetLine
DWORD
isWord32
, sofromIntegral len
call is susceptible to integer overflow, which is both incorrect and unsafe.stdcall
on 32bit OS, whileccall
forx86_64
, so some CPP is necessary