windowshaskellunicodewindows-subsystem-for-linuxlocale

Can I set the locale from within a Haskell program, so I can print unicode characters appropriately?


I'm building and running a cabal project with following code on WSL:

module Main where
main :: IO ()
main = do
  putStrLn "█"

is the unicode character 0x2588, 9608 in decimal.

When cabal running this, I get

foo: <stdout>: commitBuffer: invalid argument (cannot encode character '\9608')

So I searched online and found What might cause "commitAndReleaseBuffer: invalid argument (invalid character)" when using pandoc as a library? and verified that indeed if I run this instead

LANG=C.UTF-8 cabal run

then the program runs fine and prints the character correcly.

My question is: how do I manage this from the program itself, if at all possible?


My attempt was to use System.Locale.SetLocale.setLocale from setlocale, like this:

module Main where

import System.Locale.SetLocale

main :: IO ()
main = do
  c <- setLocale LC_ALL (Just "C.UTF-8")
  print c                                                                                                                                                                                                                              putStrLn "█"

but cabal run still errors the same way (or succeeds if I LANG=C.UTF-8 cabal run); but print c in both cases prints Just "C.UTF-8", thus making me think the call to setLocale was successful.


Solution

  • Use hSetEncoding from System.IO in base. The locale is used by GHC to set the encoding of handles, at which point changing the locale does nothing.

    Also consider fixing your locale globally because chances are, other programs that rely on the globally wrong locale won't be able to parse your program's output.