Haskell has a nice type-safe formatting library called formatting.
Underlying it is a bunch of interesting category theory that you don’t
need to know to use the library. It takes advantage of the
OverloadedStrings
extension to allow you to write something
like this:
{-# LANGUAGE OverloadedStrings #-}
module Main where
import Formatting
import qualified Data.Text as T
import qualified Data.Text.IO as T
import qualified Data.Text.Lazy as TL
who :: T.Text
= "world"
who
main :: IO ()
= T.putStrLn $ TL.toStrict $ format ("Hello, " % stext % "!") who main
Note that using the formatting with the API is a little awkward. We
can improve it by using sformat
:
= T.putStrLn $ sformat ("Hello, " % stext % "!") who main
We can improve it further by using the function fprintLn
supplied by the formatting package:
main = fprintLn ("Hello, " % stext % "!") who
I recently added a nice combinator to make it easier to add
formatting to other APIs. It’s always possible to write a function like
fprintLn above, but if you have a lot of functions that are expecting a
text value (like logging at different levels), it would be a pain to
write a formatted version of each of them. I
wrote a formatted
combinator that’s really easy to
use:
= formatted T.putStrLn ("Hello, " % stext % "!") who main
If you’re doing a lot of formatting, it may make sense to define a specific function, but it’s nice to be able to just drop in formatting somewhere with an additional keyword.