HORIZON HASKELLDocslts/ghc-9.10.x248f8f02026-10-05Search names, modules, packages, or :: a typeCtrl K

GHC 9.10.3 · lts/ghc-9.10.x · 248f8f0 · 2026-10-05

  • Packagefmt-0.6.3.0
  • Exports57
  • LanguageHaskell2010
  • LicenceBSD-3-Clause
  • SourceCore.hs

Overloaded strings

0 declarations

You need OverloadedStrings enabled to use this library. There are three ways to do it:

  • In GHCi: do :set -XOverloadedStrings.

  • In a module: add {-# LANGUAGE OverloadedStrings #-} to the beginning of your module.

  • In a project: add OverloadedStrings to the default-extensions section of your .cabal file.

Examples

0 declarations

Here's a bunch of examples because some people learn better by looking at examples.

Insert some variables into a string:

Example2 expressions
let (a, b, n) = ("foo", "bar", 25)("Here are some words: "+|a|+", "+|b|+"\nAlso a number: "+|n|+"") :: String"Here are some words: foo, bar\nAlso a number: 25"

Print it:

Example1 expression
fmtLn ("Here are some words: "+|a|+", "+|b|+"\nAlso a number: "+|n|+"")Here are some words: foo, barAlso a number: 25

Format a list in various ways:

Example1 expression
let xs = ["John", "Bob"]
Example1 expression
fmtLn ("Using show: "+||xs||+"\nUsing listF: "+|listF xs|+"")Using show: ["John","Bob"]Using listF: [John, Bob]
Example1 expression
fmt ("YAML-like:\n"+|blockListF xs|+"")YAML-like:- John- Bob
Example1 expression
fmt ("JSON-like: "+|jsonListF xs|+"")JSON-like: [  John, Bob]

Migration guide from formatting

0 declarations

Instead of using %, surround variables with +| and |+. You don't have to use sformat or anything else, and also where you were using build, int, text, etc in formatting, you don't have to use anything in fmt:

formatting    sformat ("Foo: "%build%", bar: "%int) foo bar
       fmt    "Foo: "+|foo|+", bar: "+|bar|+""

The resulting formatted string is polymorphic and can be used as String, Text, Builder or even IO (i.e. the string will be printed to the screen). However, when printing it is recommended to use fmt or fmtLn for clarity.

fmt provides lots of formatters (which are simply functions that produce Builder):

formatting    sformat ("Got another byte ("%hex%")") x
       fmt    "Got another byte ("+|hexF x|+")"

Instead of the shown formatter, either just use show or double brackets:

formatting    sformat ("This uses Show: "%shown%") foo
    fmt #1    "This uses Show: "+|show foo|+""
    fmt #2    "This uses Show: "+||foo||+""

Many formatters from formatting have the same names in fmt, but with added “F”: hexF, exptF, etc. Some have been renamed, though:

Cutting:
  fitLeft  -> prefixF
  fitRight -> suffixF

Padding:
  left   -> padLeftF
  right  -> padRightF
  center -> padBothF

Stuff with numbers:
  ords   -> ordinalF
  commas -> commaizeF

Also, some formatters from formatting haven't been added to fmt yet. Specifically:

  • plural and asInt (but instead of asInt you can use fromEnum)

  • prefixBin, prefixOrd, prefixHex, and bytes

  • formatters that use Scientific (sci and scifmt)

They will be added later. (On the other hand, fmt provides some useful formatters not available in formatting, such as listF, mapF, tupleF and so on.)

Basic formatting

0 declarations

To format strings, put variables between (+|) and (|+):

Example2 expressions
let name = "Alice" :: String"Meet "+|name|+"!" :: String"Meet Alice!"

Of course, Text is supported as well:

Example1 expression
"Meet "+|name|+"!" :: Text"Meet Alice!"

You don't actually need any type signatures; however, if you're toying with this library in GHCi, it's recommended to either add a type signature or use fmtLn:

Example1 expression
fmtLn ("Meet "+|name|+"!")Meet Alice!

Otherwise the type of the formatted string would be resolved to IO () and printed without a newline, which is not very convenient when you're in GHCi. On the other hand, it's useful for quick-and-dirty scripts:

main = do
  [fin, fout] <- words <$> getArgs
  "Reading data from "+|fin|+"\n"
  xs <- readFile fin
  "Writing processed data to "+|fout|+"\n"
  writeFile fout (show (process xs))

Anyway, let's proceed. Anything Buildable, including numbers, booleans, characters and dates, can be put between (+|) and (|+):

Example2 expressions
let starCount = "173"fmtLn ("Meet "+|name|+"! She's got "+|starCount|+" stars on Github.")Meet Alice! She's got 173 stars on Github.

Since the only thing (+|) and (|+) do is concatenate strings and do conversion, you can use any functions you want inside them. In this case, length:

Example1 expression
fmtLn (""+|name|+"'s name has "+|length name|+" letters")Alice's name has 5 letters

If something isn't Buildable, just use show on it:

Example2 expressions
let pos = (3, 5)fmtLn ("Character's position: "+|show pos|+"")Character's position: (3,5)

Or one of many formatters provided by this library – for instance, for tuples of various sizes there's tupleF:

Example1 expression
fmtLn ("Character's position: "+|tupleF pos|+"")Character's position: (3, 5)

Finally, for convenience there's the (|++|) operator, which can be used if you've got one variable following the other:

Example2 expressions
let (a, op, b, res) = (2, "*", 2, 4)fmtLn (""+|a|++|op|++|b|+" = "+|res|+"")2*2 = 4

Also, since in some codebases there are lots of types which aren't Buildable, there are operators (+||) and (||+), which use show instead of build:

Property
(""+|show foo|++|show bar|+"") == (""+||foo||++||bar||+"")

Ordinary brackets

Operators for the operators god!

Show brackets

More operators for the operators god!

Combinations

Z̸͠A̵̕͟͠L̡̀́͠G̶̛O͝ ̴͏̀ I͞S̸̸̢͠  ̢̛͘͢C̷͟͡Ó̧̨̧͞M̡͘͟͞I̷͜N̷̕G̷̀̕

(Though you can just use "" between +| |+ instead of using these operators, and Show-brackets don't have to be used at all because there's show available.)

Old-style formatting

3 declarations
valueformat :: (HasCallStack, FormatType r) => Format -> r
#

An old-style formatting function taken from text-format (see Data.Text.Format). Unlike Data.Text.Format.format from Data.Text.Format, it can produce String and strict Text as well (and print to console too). Also it's polyvariadic:

Example1 expression
format "{} + {} = {}" 2 2 42 + 2 = 4

You can use arbitrary formatters:

Example1 expression
format "0x{} + 0x{} = 0x{}" (hexF 130) (hexF 270) (hexF (130+270))0x82 + 0x10e = 0x190
newtypenewtype Format
#

A format string. This is intentionally incompatible with other string types, to make it difficult to construct a format string by concatenating string fragments (a very common way to accidentally make code vulnerable to malicious data).

This type is an instance of IsString, so the easiest way to construct a query is to enable the OverloadedStrings language extension and then simply write the query in double quotes.

{-# LANGUAGE OverloadedStrings #-}

import Fmt

f :: Format
f = "hello {}"

The underlying type is Text, so literal Haskell strings that contain Unicode characters will be correctly handled.

Instances6Eq, Ord, Show, IsString, Semigroup, Monoid
  • Eq FormatDefined in fmt-0.6.3.0 · Fmt.Internal.Template
  • Ord FormatDefined in fmt-0.6.3.0 · Fmt.Internal.Template
  • Show FormatDefined in fmt-0.6.3.0 · Fmt.Internal.Template
  • IsString FormatDefined in fmt-0.6.3.0 · Fmt.Internal.Template
  • Semigroup FormatDefined in fmt-0.6.3.0 · Fmt.Internal.Template
  • Monoid FormatDefined in fmt-0.6.3.0 · Fmt.Internal.Template

Helper functions

6 declarations
valuefmt :: FromBuilder b => Builder -> b
#

fmt converts things to String, Text, ByteString or Builder.

Most of the time you won't need it, as strings produced with (+|) and (|+) can already be used as String, Text, etc. However, combinators like listF can only produce Builder (for better type inference), and you need to use fmt on them.

Also, fmt can do printing:

Example1 expression
fmt "Hello world!\n"Hello world!
newtypenewtype Builder
#

A Builder is an efficient way to build lazy Text values. There are several functions for constructing builders, but only one to inspect them: to extract any data, you have to turn them into lazy Text values using toLazyText.

Internally, a builder constructs a lazy Text by filling arrays piece by piece. As each buffer is filled, it is 'popped' off, to become a new chunk of the resulting lazy Text. All this is hidden from the user of the Builder.

Instances10Eq, Ord, Show, IsString, Semigroup, Monoid, …
  • Eq BuilderDefined in text-2.1.3 · Data.Text.Internal.Builder
  • Ord BuilderDefined in text-2.1.3 · Data.Text.Internal.Builder
  • Show BuilderDefined in text-2.1.3 · Data.Text.Internal.Builder
  • IsString BuilderDefined in text-2.1.3 · Data.Text.Internal.Builder

    Performs replacement on invalid scalar values:

    Example2 expressions
    :set -XOverloadedStrings"\55555" :: Builder"\65533"
  • Semigroup BuilderDefined in text-2.1.3 · Data.Text.Internal.Builder
  • Monoid BuilderDefined in text-2.1.3 · Data.Text.Internal.Builder
  • Buildable BuilderDefined in formatting-7.2.0 · Formatting.Buildable
  • FromBuilder BuilderDefined in formatting-7.2.0 · Formatting.FromBuilder
  • FromBuilder BuilderDefined in fmt-0.6.3.0 · Fmt.Internal.Core
  • TupleF [Builder]Defined in fmt-0.6.3.0 · Fmt.Internal.Tuple
classclass Buildable p where
#

The class of types that can be rendered to a Builder.

Methods

Instances39Buildable, …

Formatters

0 declarations

Time

module Fmt.Time

Text

valueindentF :: Int -> Builder -> Builder
#

Indent a block of text.

Example1 expression
fmt $ "This is a list:\n" <> indentF 4 (blockListF [1,2,3])This is a list:    - 1    - 2    - 3

The output will always end with a newline, even when the input doesn't.

valueindentF' :: Int -> Text -> Builder -> Builder
#

Add a prefix to the first line, and indent all lines but the first one.

The output will always end with a newline, even when the input doesn't.

valuenameF :: Builder -> Builder -> Builder
#

Attach a name to anything:

Example1 expression
fmt $ nameF "clients" $ blockListF ["Alice", "Bob", "Zalgo"]clients:  - Alice  - Bob  - Zalgo
valueunwordsF :: (Foldable f, Buildable a) => f a -> Builder
#

Put spaces between elements.

Example1 expression
fmt $ unwordsF ["hello", "world"]hello world

Of course, it works on anything Buildable:

Example1 expression
fmt $ unwordsF [1, 2]1 2
valueunlinesF :: (Foldable f, Buildable a) => f a -> Builder
#

Arrange elements on separate lines.

Example1 expression
fmt $ unlinesF ["hello", "world"]helloworld

Lists

valuelistF :: (Foldable f, Buildable a) => f a -> Builder
#

A simple comma-separated list formatter.

Example1 expression
listF ["hello", "world"]"[hello, world]"

For multiline output, use jsonListF.

valuelistF' :: Foldable f => (a -> Builder) -> f a -> Builder
#

A version of listF that lets you supply your own building function for list elements.

For instance, to format a list of numbers as hex:

Example1 expression
listF' hexF [1234, 5678]"[4d2, 162e]"
valueblockListF :: (Foldable f, Buildable a) => f a -> Builder
#

A multiline formatter for lists.

Example1 expression
fmt $ blockListF [1,2,3]- 1- 2- 3

Multi-line elements are indented correctly:

Example1 expression
fmt $ blockListF ["hello\nworld", "foo\nbar\nquix"]- hello  world- foo  bar  quix
valueblockListF'
  1. :: Foldable f
  2. => Text

    Bullet

  3. -> (a -> Builder)

    Builder for elements

  4. -> f a

    Structure with elements

  5. -> Builder
#

A version of blockListF that lets you supply your own building function for list elements (instead of build) and choose the bullet character (instead of "-").

valuejsonListF :: (Foldable f, Buildable a) => f a -> Builder
#

A JSON-style formatter for lists.

Example1 expression
fmt $ jsonListF [1,2,3][  1, 2, 3]

Like blockListF, it handles multiline elements well:

Example1 expression
fmt $ jsonListF ["hello\nworld", "foo\nbar\nquix"][  hello  world, foo  bar  quix]

Maps

valuemapF
  1. :: (IsList t, Item t ~ (k, v), Buildable k, Buildable v)
  2. => t
  3. -> Builder
#

A simple JSON-like map formatter; works for Map, HashMap, etc, as well as ordinary lists of pairs.

Example1 expression
mapF [("a", 1), ("b", 4)]"{a: 1, b: 4}"

For multiline output, use jsonMapF.

valueblockMapF
  1. :: (IsList t, Item t ~ (k, v), Buildable k, Buildable v)
  2. => t
  3. -> Builder
#

A YAML-like map formatter:

Example1 expression
fmt $ blockMapF [("Odds", blockListF [1,3]), ("Evens", blockListF [2,4])]Odds:  - 1  - 3Evens:  - 2  - 4
valuejsonMapF
  1. :: (IsList t, Item t ~ (k, v), Buildable k, Buildable v)
  2. => t
  3. -> Builder
#

A JSON-like map formatter (unlike mapF, always multiline):

Example1 expression
fmt $ jsonMapF [("Odds", jsonListF [1,3]), ("Evens", jsonListF [2,4])]{  Odds:    [      1    , 3    ], Evens:    [      2    , 4    ]}

Tuples

methodtupleF :: a -> Builder
#

Format a tuple (of up to 8 elements):

Example1 expression
tupleF (1,2,"hi")"(1, 2, hi)"

If any of the elements takes several lines, an alternate format is used:

Example1 expression
fmt $ tupleF ("test","foo\nbar","more test")( test,  foo  bar,  more test )

You can also use tupleF on lists to get tuple-like formatting.

ADTs

valuemaybeF :: Buildable a => Maybe a -> Builder
#

Like build for Maybe, but displays Nothing as <Nothing> instead of an empty string.

build:

Example2 expressions
build (Nothing :: Maybe Int)""build (Just 1 :: Maybe Int)"1"

maybeF:

Example2 expressions
maybeF (Nothing :: Maybe Int)"<Nothing>"maybeF (Just 1 :: Maybe Int)"1"

Padding/trimming

valuepadLeftF :: Buildable a => Int -> Char -> a -> Builder
#

padLeftF n c pads the string with character c from the left side until it becomes n characters wide (and does nothing if the string is already that long, or longer):

Example2 expressions
padLeftF 5 '0' 12"00012"padLeftF 5 '0' 123456"123456"
valuepadRightF :: Buildable a => Int -> Char -> a -> Builder
#

padRightF n c pads the string with character c from the right side until it becomes n characters wide (and does nothing if the string is already that long, or longer):

Example2 expressions
padRightF 5 ' ' "foo""foo  "padRightF 5 ' ' "foobar""foobar"
valuepadBothF :: Buildable a => Int -> Char -> a -> Builder
#

padBothF n c pads the string with character c from both sides until it becomes n characters wide (and does nothing if the string is already that long, or longer):

Example2 expressions
padBothF 5 '=' "foo""=foo="padBothF 5 '=' "foobar""foobar"

When padding can't be distributed equally, the left side is preferred:

Example1 expression
padBothF 8 '=' "foo""===foo=="

Hex

methodhexF :: a -> Builder
#

Format a number or bytestring as hex:

Example2 expressions
hexF 3635"e33"hexF ("\0\50\63\80" :: BS.ByteString)"00323f50"

Bytestrings

methodbase64F :: a -> Builder
#

Convert a bytestring to base64:

Example1 expression
base64F ("\0\50\63\80" :: BS.ByteString)"ADI/UA=="
methodbase64UrlF :: a -> Builder
#

Convert a bytestring to base64url (a variant of base64 which omits / and thus can be used in URLs):

Example1 expression
base64UrlF ("\0\50\63\80" :: BS.ByteString)"ADI_UA=="

Integers

Base conversion

valueoctF :: Integral a => a -> Builder
#

Format a number as octal:

Example1 expression
listF' octF [7,8,9,10]"[7, 10, 11, 12]"
valuebinF :: Integral a => a -> Builder
#

Format a number as binary:

Example1 expression
listF' binF [7,8,9,10]"[111, 1000, 1001, 1010]"
valuebaseF :: (HasCallStack, Integral a) => Int -> a -> Builder
#

Format a number in arbitrary base (up to 36):

Example3 expressions
baseF 3 10000"111201101"baseF 7 10000"41104"baseF 36 10000"7ps"

Floating-point

valuefloatF :: Real a => a -> Builder
#

Format a floating-point number:

Example1 expression
floatF 3.1415"3.1415"

Numbers smaller than 1e-6 or bigger-or-equal to 1e21 will be displayed using scientific notation:

Example3 expressions
listF' floatF [-1.2,-12.2]"[-1.2, -12.2]"listF' floatF [1e-6,9e-7]"[0.000001, 9.0e-7]"listF' floatF [9e20,1e21]"[900000000000000000000.0, 1.0e21]"
valueexptF :: Real a => Int -> a -> Builder
#

Format a floating-point number using scientific notation, with the given amount of decimal places.

Example1 expression
listF' (exptF 5) [pi,0.1,10]"[3.14159e0, 1.00000e-1, 1.00000e1]"
valuefixedF :: Real a => Int -> a -> Builder
#

Format a floating-point number without scientific notation:

Example1 expression
listF' (fixedF 5) [pi,0.1,10]"[3.14159, 0.10000, 10.00000]"

Conditional formatting

valuewhenF :: Bool -> Builder -> Builder
#

Display something only if the condition is True (empty string otherwise).

Note that it can only take a Builder (because otherwise it would be unusable with (+|)-formatted strings which can resolve to any FromBuilder). You can use build to convert any value to a Builder.

Generic formatting

valuegenericF :: (Generic a, GBuildable (Rep a)) => a -> Builder
#

Format an arbitrary value without requiring a Buildable instance:

Example1 expression
data Foo = Foo { x :: Bool, y :: [Int] } deriving Generic
Example1 expression
fmt (genericF (Foo True [1,2,3]))Foo:  x: True  y: [1, 2, 3]

It works for non-record constructors too:

Example1 expression
data Bar = Bar Bool [Int] deriving Generic
Example1 expression
fmtLn (genericF (Bar True [1,2,3]))<Bar: True, [1, 2, 3]>

Any fields inside the type must either be Buildable or one of the following types:

The exact format of genericF might change in future versions, so don't rely on it. It's merely a convenience function.

newtypenewtype GenericBuildable a
#

A newtype for deriving a generic Buildable instance for any type using DerivingVia.

Example2 expressions
:set -XDerivingVia:{data Bar = Bar { x :: Bool, y :: [Int] }  deriving stock Generic  deriving Buildable via GenericBuildable Bar:}
Example1 expression
pretty (Bar True [1,2,3])Bar:  x: True  y: [1, 2, 3]

Constructors

Instances1Buildable