Get your IO right on the first try
Go to file
serokell-bot abfd13f909
Automatically update flake.lock to the latest version (#29)
hackage  de3d2b30f3 (2024-01-17) -> a62dac66a9 (2024-05-13)
nixpkgs  f724378e61 (2024-01-15) -> sha256-dd/ (1970-01-01)
stackage ad9de7aee0 (2024-01-17) -> 207b7104d5 (2024-05-12)
2024-05-14 13:37:44 +03:00
.github/workflows [Chore] Update "actions/checkout" 2023-12-12 12:41:14 +01:00
app/utf8-troubleshoot Disable one HLint warning 2024-01-10 22:29:19 +01:00
lib Deprecate Data.Text.IO.Utf8 2024-01-16 22:00:20 +01:00
LICENSES [Chore] Use new flake template 2023-03-20 23:46:53 +03:00
test Deprecate Data.Text.IO.Utf8 2024-01-16 22:00:20 +01:00
.gitignore meta: Commit the .cabal file 2020-05-15 16:29:45 +03:00
.stylish-haskell.yaml [Chore] Use new flake template 2023-03-20 23:46:53 +03:00
CHANGELOG.md Bump the version of the package 2024-01-16 22:07:28 +01:00
CHANGELOG.md.license license: Remove header from changelog to make Hackage happy 2020-05-15 16:24:53 +03:00
default.nix [Chore] Use new flake template 2023-03-20 23:46:53 +03:00
flake.lock Automatically update flake.lock to the latest version (#29) 2024-05-14 13:37:44 +03:00
flake.lock.license [Chore] Use new flake template 2023-03-20 23:46:53 +03:00
flake.nix Test GHC 9.6 and 9.8 on CI 2024-01-10 22:34:10 +01:00
package.yaml Bump the version of the package 2024-01-16 22:07:28 +01:00
README.md Deprecate Data.Text.IO.Utf8 2024-01-16 22:00:20 +01:00
README.md.license license: Move tags from dep5 to .license files 2020-05-15 16:25:44 +03:00
stack.yaml Update stackage resolver 2024-01-10 22:34:19 +01:00
stack.yaml.lock Update stackage resolver 2024-01-10 22:34:19 +01:00
stack.yaml.lock.license license: Move tags from dep5 to .license files 2020-05-15 16:25:44 +03:00
with-utf8.cabal Bump the version of the package 2024-01-16 22:07:28 +01:00
with-utf8.cabal.license [Chore] Use new flake template 2023-03-20 23:46:53 +03:00

with-utf8

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.

Use

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), youll probably use withFile, openFile, or readFile. Grab the first two from System.IO.Utf8 or the latter from Data.Text.IO.Utf8. Starting from text-2.1, Data.Text.IO.Utf8 is available in the text package itself, hence this module in with-utf8 is now deprecated.

Note: it is best to import these modules qualified.

Note: there is no System.IO.Utf8.readFile because its 2024 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. Starting from text-2.1, Data.Text.IO.Utf8 is available in the text package itself, hence this module in with-utf8 is now deprecated.

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.

Troubleshooting

Locales are pretty straightforward, but some people might have their terminals misconfigured for various reasons. To help troubleshoot any potential issues, this package comes with a tool called utf8-troubleshoot.

This tool outputs some basic information about locale settings in the OS and what they end up being mapped to in Haskell. If you are looking for help, please, provide the output of this tool, or if you are helping someone, ask them to run this tool and provide the output.

Contributing

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.

License

MPL-2.0 © Serokell