with-utf8: Get your IO right on the first try

This is a package candidate release! Here you can preview how this package release will appear once published to the main package index (which can be accomplished via the 'maintain' link below). Please note that once a package has been published to the main package index it cannot be undone! Please consult the package uploading documentation for more information.

[maintain] [Publish]

This minimalistic library helps you navigate the world of text encodings avoiding invalid argument (invalid byte sequence) and invalid argument (invalid character) in runtime.

The two most important modules are:

See this blog post for why this library exists and what exactly it does.

[Skip to Readme]


Versions 1.0.0,,,,,,,,
Change log CHANGELOG.md
Dependencies base (>=4.10 && <4.14), safe-exceptions (>=0.1 && <0.2), text (>=0.7 && <1.3) [details]
License MPL-2.0
Copyright 2020 Serokell
Author Kirill Elagin <kirelagin@serokell.io>
Maintainer Kirill Elagin <kirelagin@serokell.io>
Category IO
Home page https://github.com/serokell/haskell-with-utf8#readme
Bug tracker https://github.com/serokell/haskell-with-utf8/issues
Source repo head: git clone https://github.com/serokell/haskell-with-utf8
Uploaded by kirelagin at 2020-02-27T03:47:53Z



Maintainer's Corner

Package maintainers

For package maintainers and hackage trustees

Readme for with-utf8-1.0.0

[back to package description]


Get your IO right on the first try.

Reading files in Haskell is trickier than it could be due to the non-obvious interactions between file encodings and system locale. This library is meant to make it easy once and for all by providing “defaults” that make more sense in the modern world.

See this blog post for more details on why this library needs to exists and an explanation of some of the opinionated decisions it is based on.


See the documentation on Hackage for details, this is a quick summary.

Step 1: Get it

The library is on Hackage, go ahead and add it to the dependencies of your project.

Step 2: Wrap your main

Import withUtf8 from Main.Utf8 and wrap it around your main:

import Main.Utf8 (withUtf8)

main :: IO ()
main = withUtf8 $
  {- ... your main function ... -}

This will make sure that if your program reads something from stdin or outputs something to stdout/stderr, it will not fail with a runtime error due to encoding issues.

Step 3: Read files using UTF-8

If you are going to read a text file (to be precise, if you are going to open a file in text mode), you’ll probably use withFile, openFile, or readFile. Grab the first two from System.IO.Utf8 or the latter from Data.Text.IO.Utf8.

Note: it is best to import these modules qualified.

Note: there is no System.IO.Utf8.readFile because it’s 2020 and you should not read Strings from files.

All these functions will make sure that the content will be treated as if it was encoded in UTF-8.

If, for some reason, you really need to use withFile/openFile from base, or you got your file handle from somewhere else, wrap the code that works with it in a call to withHandle from System.IO.Utf8:

import qualified System.IO as IO
import qualified System.IO.Utf8 as Utf8

doSomethingWithAFile :: IO.Handle -> IO ()
doSomethingWithAFile h = Utf8.withhandle h $ do
    {- ... work with the file ... -}

Step 4: Write files using UTF-8

When writing a file either open it using withFile/openFile from System.IO.Utf8 or write to it directly with writeFile from Data.Text.IO.Utf8.

Note: it is best to import these modules qualified.

Note: there is no System.IO.Utf8.writeFile.

If, for some reason, you really need to use withFile/openFile from base, do the same as in the previous step.


If you encounter any issues when using this library or have improvement ideas, please open report in issue on GitHub. You are also very welcome to submit pull request, if you feel like doing so.


MPL-2.0 © Serokell