Haskell: print TextEncoding

2019-06-25 23:57发布

问题:

Haskell newbie here.

$ ghc --version
The Glorious Glasgow Haskell Compilation System, version 6.12.1

While trying to debug weird locale-related bug in third-party Haskell program, I'm trying to print default encoding:

import System.IO
main = do
  print localeEncoding

But it fails:

$ ghc -o printlocale main.hs
main.hs:4:2:
    No instance for (Show TextEncoding)
      arising from a use of `print' at main.hs:4:2-21
    Possible fix: add an instance declaration for (Show TextEncoding)
    In the expression: print localeEncoding
    In the expression: do { print localeEncoding }
    In the definition of `main': main = do { print localeEncoding }

My google-fu is failing me. What am I missing?

回答1:

To print a value of some type in Haskell, the type must be an instance of the Show class.

localeEncoding :: TextEncoding

and TextEncoding is not an instance of Show.

The TextEncoding type is actually an existential type storing the methods for encoding and decoding:

data TextEncoding
  = forall dstate estate . TextEncoding  {
    mkTextDecoder :: IO (TextDecoder dstate),
    mkTextEncoder :: IO (TextEncoder estate)
  }

Since these are functions, there's no sensible way to show them. The current localeEncoding is determined using iconv, via the C function nl_langinfo.

So, TextEncoding as such is not a showable type, so you cannot print it. However, you can construct new values of this type, via mkTextEncoding. E.g. to create a utf8 environment:

mkTextEncoding "UTF-8" 

We might consider a feature request to store the representation of the locale with the TextEncoding, so this label could be printed. However, that's currently not possible.