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

Moduleformatting-7.2.0Haskell2010

Formatting.Combinators

A formatting combinator takes a Format and returns another Format. Generally we want to change what the original format takes as its *input*, leaving the output polymorphic. Many of these combinators can be chained together to form a single Format.

Implementation detail: in order to be able to chain multiple combinators to make a single Format we need them all to use the same intermediate string type, and we have chosen Builder. This does not tie you to using Builders, because the final output string type r is still polymorphic.

  • 61 values
  • Packageformatting-7.2.0
  • Exports61
  • LanguageHaskell2010
  • LicenceBSD-3-Clause
  • SourceCombinators.hs

Formatting common containers

5 declarations
valuemaybed
  1. :: Builder

    The value to use when the input is Nothing

  2. -> Format Builder (a -> Builder)

    The formatter to use on the value in a Just

  3. -> Format r (Maybe a -> r)
#

Render a Maybe value either as a default (if Nothing) or using the given formatter:

Example1 expression
format (maybed "Goodbye" text) Nothing"Goodbye"
Example1 expression
format (maybed "Goodbye" text) (Just "Hello")"Hello"
valueoptioned :: Format Builder (a -> Builder) -> Format r (Maybe a -> r)
#

Render the value in a Maybe using the given formatter, or produce an empty string:

Example1 expression
format (optioned text) Nothing""
Example1 expression
format (optioned text) (Just "Hello")"Hello"
valueeithered
  1. :: Format Builder (a -> Builder)

    The formatter to use on a value in a Left

  2. -> Format Builder (b -> Builder)

    The formatter to use on a value in a Right

  3. -> Format r (Either a b -> r)
#

Render the value in an Either:

Example1 expression
format (eithered text int) (Left "Error!")"Error!"
Example1 expression
format (eithered text int) (Right 69)"69"
valuelefted :: Format Builder (a -> Builder) -> Format r (Either a x -> r)
#

Render the value in a Left with the given formatter, rendering a Right as an empty string:

Example1 expression
format (lefted text) (Left "bingo")"bingo"
Example1 expression
format (lefted text) (Right 16)""
valuerighted :: Format Builder (a -> Builder) -> Format r (Either x a -> r)
#

Render the value in a Right with the given formatter, rendering a Left as an empty string:

Example1 expression
format (righted text) (Left 16)""
Example1 expression
format (righted text) (Right "bingo")"bingo"

Formatting lists of data

12 declarations
valueconcatenated
  1. :: Foldable t
  2. => Format Builder (a -> Builder)
  3. -> Format r (t a -> r)
#

Format each value in a list and concatenate them all:

Example1 expression
format (concatenated text) ["one", "two", "three"]"onetwothree"
Example1 expression
format (took 15 (concatenated bin)) [1..]"1101110010111011110001001101010111100110111101111"
valuejoinedWith
  1. :: Foldable t
  2. => [Text] -> Text
  3. -> Format Builder (a -> Builder)
  4. -> Format r (t a -> r)
#

Use the given text-joining function to join together the individually rendered items of a list.

Example1 expression
format (joinedWith (mconcat . reverse) int) [123, 456, 789]"789456123"
valuespaced :: Foldable t => Format Builder (a -> Builder) -> Format r (t a -> r)
#

Separate the formatted items of the Foldable (e.g. list) with spaces:

Example1 expression
format (spaced int) [1, 2, 3]"1 2 3"

Note that this behaviour is identical to unworded, it's just a different way of thinking about it.

valuecommaSep
  1. :: Foldable t
  2. => Format Builder (a -> Builder)
  3. -> Format r (t a -> r)
#

Separate the formatted items of the Foldable (e.g. list) with commas:

Example1 expression
format (commaSep stext) ["one", "two", "three", "four", "five"]"one,two,three,four,five"
Example1 expression
format (took 5 (commaSep int)) [1..]"1,2,3,4,5"
valuecommaSpaceSep
  1. :: Foldable t
  2. => Format Builder (a -> Builder)
  3. -> Format r (t a -> r)
#

Separate the formatted items of the Foldable (e.g. list) with commas and spaces:

Example1 expression
format (took 3 (commaSpaceSep ords)) [1..]"1st, 2nd, 3rd"
valuelist :: Foldable t => Format Builder (a -> Builder) -> Format r (t a -> r)
#

Add square brackets around the Foldable (e.g. a list), and separate each formatted item with a comma and space.

Example1 expression
format (list stext) ["one", "two", "three"]"[one, two, three]"
Example1 expression
format (list shown) ["one", "two", "three"]"[\"one\", \"two\", \"three\"]"
valueqlist :: Foldable t => Format Builder (a -> Builder) -> Format r (t a -> r)
#

Like list, but also put double quotes around each rendered item:

Example1 expression
fprintLn (qlist stext) ["one", "two", "three"]["one", "two", "three"]
valuetook :: Int -> Format r ([a] -> r) -> Format r ([a] -> r)
#

Take only the first n items from the list of items.

Example1 expression
format (took 7 (list bin)) [1..]"[1, 10, 11, 100, 101, 110, 111]"
Example1 expression
format (list bin) (take 7 [1..])"[1, 10, 11, 100, 101, 110, 111]"
valuedropped :: Int -> Format r ([a] -> r) -> Format r ([a] -> r)
#

Drop the first n items from the list of items.

Example1 expression
format (dropped 3 (list int)) [1..6]"[4, 5, 6]"

Splitting strings to pass to other formatters

5 declarations
valuesplat
  1. :: (Char -> Bool)

    Whether to split the string at this character

  2. -> (Format r' (Builder -> r') -> Format Builder ([Builder] -> Builder))

    A list-formatting combinator, e.g. unworded, list, concatenated, etc.

  3. -> Format r a

    The base formatter, whose rendered text will be split

  4. -> Format r a
#

Split the formatted item in places the given predicated matches, and use the given list combinator to render the resultant list of strings (this function was sent to us from a parallel universe in which splat is the past participle of split, e.g. "whoops, I splat my pants").

Example1 expression
format (splat Data.Char.isSpace commaSpaceSep stext) "This\t  is\n\t\t  poorly formatted   ""This, , , is, , , , , poorly, formatted, , , "
valuesplatOn
  1. :: Text

    The text to split on

  2. -> (Format r' (Builder -> r') -> Format Builder ([Builder] -> Builder))

    A list-formatting combinator, e.g. unworded, list, concatenated, etc.

  3. -> Format r a

    The base formatter, whose rendered text will be split

  4. -> Format r a
#

Split the formatted item at instances of the given string, and use the given list combinator to render the resultant list of strings.

Example1 expression
fprint (splatOn "," unlined text) "one,two,three"onetwothree
Example1 expression
fprint (splatOn "," (indentedLines 4) text) "one,two,three"    one    two    three
valueworded
  1. :: (Format r' (Builder -> r') -> Format Builder ([Builder] -> Builder))

    A list-formatting combinator, e.g. unworded, list, concatenated, etc.

  2. -> Format r a

    The base formatter, whose rendered text will be split

  3. -> Format r a
#

Split the formatted item into words and use the given list combinator to render the resultant list of strings.

Example1 expression
format (worded list text) "one  two three  ""[one, two, three]"
valuelined
  1. :: (Format Builder (Builder -> Builder) -> Format Builder ([Builder] -> Builder))

    A list-formatting combinator, e.g. unworded, list, concatenated, etc.

  2. -> Format r a

    The base formatter, whose rendered text will be split

  3. -> Format r a
#

Split the formatted item into lines and use the given list combinator to render the resultant list of strings.

Example1 expression
fprintLn (lined qlist text) "one two three\n\nfour five six\nseven eight nine\n\n"["one two three", "", "four five six", "seven eight nine", ""]

Altering formatted strings

16 declarations
valuealteredWith :: (Text -> Text) -> Format r a -> Format r a
#

Alter the formatted string with the given function.

Example1 expression
format (alteredWith Data.Text.Lazy.reverse int) 123456"654321"
valuecharsKeptIf :: (Char -> Bool) -> Format r a -> Format r a
#

Filter the formatted string to contain only characters which pass the given predicate:

Example1 expression
format (charsKeptIf Data.Char.isUpper text) "Data.Char.isUpper""DCU"
valuecharsRemovedIf :: (Char -> Bool) -> Format r a -> Format r a
#

Filter the formatted string to not contain characters which pass the given predicate:

Example1 expression
format (charsRemovedIf Data.Char.isUpper text) "Data.Char.isUpper""ata.har.ispper"
valuereplaced :: Text -> Text -> Format r a -> Format r a
#

Take a formatter and replace the given needle with the given replacement in its output.

Example1 expression
format (replaced "Bruce" "<redacted>" stext) "Bruce replied that Bruce's name was, in fact, '<redacted>'.""<redacted> replied that <redacted>'s name was, in fact, '<redacted>'."
valueuppercased :: Format r a -> Format r a
#

Convert any letters in the output of the given formatter to upper-case.

Example1 expression
format (uppercased text) "I'm not shouting, you're shouting.""I'M NOT SHOUTING, YOU'RE SHOUTING."
valuelowercased :: Format r a -> Format r a
#

Convert any letters in the output of the given formatter to lower-case.

Example1 expression
format (lowercased text) "Cd SrC/; Rm -Rf *""cd src/; rm -rf *"
valuetitlecased :: Format r a -> Format r a
#

Convert the formatted string to title case, or something like it:

Example1 expression
format (titlecased string) "the life of brian""The Life Of Brian"
valueltruncated :: Int64 -> Format r a -> Format r a
#

Truncate the formatted string at the end so that it is no more than the given number of characters in length, placing an ellipsis at the end such that it does not exceed this length.

Example1 expression
format (ltruncated 5 text) "hello""hello"
Example1 expression
format (ltruncated 5 text) "hellos""he..."
valuectruncated :: Int64 -> Int64 -> Format r a -> Format r a
#

Truncate the formatted string in the center, leaving the given number of characters at the start and end, and placing an ellipsis in between. The length will be no longer than `start + end + 3` characters long.

Example1 expression
format (ctruncated 15 4 text) "The quick brown fox jumps over the lazy dog.""The quick brown...dog."
Example1 expression
format (ctruncated 15 4 text) "The quick brown fox""The quick brown fox"
valuertruncated :: Int64 -> Format r a -> Format r a
#

Truncate the formatted string at the start so that it is no more than the given number of characters in length, placing an ellipsis at the start such that it does not exceed this length.

Example1 expression
format (rtruncated 5 text) "hello""hello"
Example1 expression
format (rtruncated 5 text) "hellos""...os"
valuelpadded :: Int64 -> Char -> Format r (a -> r) -> Format r (a -> r)
#

Pad the formatted string on the left with the given character to give it the given minimum width:

Example1 expression
format (lpadded 7 ' ' int) 1"      1"
Example1 expression
format (lpadded 7 ' ' int) 123456789"123456789"
valuerpadded :: Int64 -> Char -> Format r (a -> r) -> Format r (a -> r)
#

Pad the formatted string on the right with the given character to give it the given minimum width:

Example1 expression
format (rpadded 7 ' ' int) 1"1      "
valuecpadded :: Int64 -> Char -> Format r (a -> r) -> Format r (a -> r)
#

Pad the formatted string on the left and right with the given character to center it, giving it the given minimum width:

Example1 expression
format (cpadded 7 ' ' int) 1"   1   "
valuelfixed :: Int64 -> Char -> Format r (a -> r) -> Format r (a -> r)
#

Format the item with a fixed width, padding with the given character on the left to extend, adding an ellipsis on the right to shorten:

Example1 expression
format (lfixed 10 ' ' int) 123"123       "
Example1 expression
format (lfixed 10 ' ' int) 1234567890"1234567890"
Example1 expression
format (lfixed 10 ' ' int) 123456789012345"1234567..."
valuerfixed :: Int64 -> Char -> Format r (a -> r) -> Format r (a -> r)
#

Format the item with a fixed width, padding with the given character on the right to extend, adding an ellipsis on the right to shorten:

Example1 expression
format (rfixed 10 ' ' int) 123"       123"
Example1 expression
format (rfixed 10 ' ' int) 1234567890"1234567890"
Example1 expression
format (rfixed 10 ' ' int) 123456789012345"...9012345"
valuecfixed :: Int64 -> Int64 -> Char -> Format r (a -> r) -> Format r (a -> r)
#

Format the item with a fixed width, padding with the given character on either side to extend, adding an ellipsis in the center to shorten.

The total length will be `l + r + 3` characters.

Example1 expression
format (cfixed 4 3 ' ' int) 123"    123   "
Example1 expression
format (cfixed 4 3 ' ' int) 1234567890"1234567890"
Example1 expression
format (cfixed 4 3 ' ' int) 123456789012345"1234...345"

Wrapping formatted strings

11 declarations
valueprefixed :: Builder -> Format r a -> Format r a
#

Add the given prefix to the formatted item:

Example1 expression
format ("The answer is: " % prefixed "wait for it... " int) 42"The answer is: wait for it... 42"
Example1 expression
fprint (unlined (indented 4 (prefixed "- " int))) [1, 2, 3]    - 1    - 2    - 3
valuesurrounded :: Builder -> Format r a -> Format r a
#

Surround the output string with the given string:

Example1 expression
format (surrounded "***" string) "glue""***glue***"
valueenclosed :: Builder -> Builder -> Format r a -> Format r a
#

Enclose the output string with the given strings:

Example1 expression
format (enclosed "<!--" "-->" text) "an html comment""<!--an html comment-->"
valuesquoted :: Format r a -> Format r a
#

Add single quotes around the formatted item:

Example1 expression
let obj = Just Nothing in format ("The object is: " % squoted shown % ".") obj"The object is: 'Just Nothing'."
valuedquoted :: Format r a -> Format r a
#

Add double quotes around the formatted item:

Example1 expression
fprintLn ("He said it was based on " % dquoted stext % ".") "science"He said it was based on "science".
valueparenthesised :: Format r a -> Format r a
#

Add parentheses around the formatted item:

Example1 expression
format ("We found " % parenthesised int % " discrepancies.") 17"We found (17) discrepancies."
Example1 expression
fprintLn (took 5 (list (parenthesised int))) [1..][(1), (2), (3), (4), (5)]
valuesquared :: Format r a -> Format r a
#

Add square brackets around the formatted item:

Example1 expression
format (squared int) 7"[7]"
valuebraced :: Format r a -> Format r a
#

Add curly brackets around the formatted item:

Example1 expression
format ("\\begin" % braced text) "section""\\begin{section}"
valueangled :: Format r a -> Format r a
#

Add angle brackets around the formatted item:

Example1 expression
format (angled int) 7"<7>"
Example1 expression
format (list (angled text)) ["html", "head", "title", "body", "div", "span"]"[<html>, <head>, <title>, <body>, <div>, <span>]"
valuebackticked :: Format r a -> Format r a
#

Add backticks around the formatted item:

Example1 expression
format ("Be sure to run " % backticked builder % " as root.") ":(){:|:&};:""Be sure to run `:(){:|:&};:` as root."

Changing indentation

3 declarations
valueindented :: Int -> Format r a -> Format r a
#

Insert the given number of spaces at the start of the rendered text:

Example1 expression
format (indented 4 int) 7"    7"

Note that this only indents the first line of a multi-line string. To indent all lines see reindented.

valueindentedLines
  1. :: Foldable t
  2. => Int
  3. -> Format Builder (a -> Builder)
  4. -> Format r (t a -> r)
#

Format a list of items, placing one per line, indented by the given number of spaces.

Example1 expression
fprint ("The lucky numbers are:\n" % indentedLines 4 int) [7, 13, 1, 42]The lucky numbers are:    7    13    1    42
valuereindented :: Int -> Format r a -> Format r a
#

Indent each line of the formatted string by the given number of spaces:

Example1 expression
fprint (reindented 2 text) "one\ntwo\nthree"  one  two  three

Numerical adapters

4 declarations
valueroundedTo :: (Integral i, RealFrac d, Functor f) => f (i -> r) -> f (d -> r)
#

Take a fractional number and round it before formatting it as the given Format:

Example2 expressions
format (roundedTo int) 6.66"7"format (list (roundedTo int)) [10.66, 6.66, 1.0, 3.4]"[11, 7, 1, 3]"

Note: the type variable f will almost always be 'Format r', so the type of this function can be thought of as:

roundedTo :: (Integral i, RealFrac d) => Format r (i -> r) -> Format r (d -> r)
valuetruncatedTo
  1. :: (Integral i, RealFrac d, Functor f)
  2. => f (i -> r)
  3. -> f (d -> r)
#

Take a fractional number and truncate it before formatting it as the given Format:

Example2 expressions
format (truncatedTo int) 6.66"6"format (list (truncatedTo int)) [10.66, 6.66, 1.0, 3.4]"[10, 6, 1, 3]"

Note: the type variable f will almost always be 'Format r', so the type of this function can be thought of as:

truncatedTo :: (Integral i, RealFrac d) => Format r (i -> r) -> Format r (d -> r)
valueceilingedTo
  1. :: (Integral i, RealFrac d, Functor f)
  2. => f (i -> r)
  3. -> f (d -> r)
#

Take a fractional number and ceiling it before formatting it as the given Format:

Example2 expressions
format (ceilingedTo int) 6.66"7"format (list (ceilingedTo int)) [10.66, 6.66, 1.0, 3.4]"[11, 7, 1, 4]"

Note: the type variable f will almost always be 'Format r', so the type of this function can be thought of as:

ceilingedTo :: (Integral i, RealFrac d) => Format r (i -> r) -> Format r (d -> r)
valueflooredTo :: (Integral i, RealFrac d, Functor f) => f (i -> r) -> f (d -> r)
#

Take a fractional number and floor it before formatting it as the given Format:

Example2 expressions
format (flooredTo int) 6.66"6"format (list (flooredTo int)) [10.66, 6.66, 1.0, 3.4]"[10, 6, 1, 3]"

Note: the type variable f will almost always be 'Format r', so the type of this function can be thought of as:

flooredTo :: (Integral i, RealFrac d) => Format r (i -> r) -> Format r (d -> r)

Structure formatting

2 declarations
valueviewed
  1. :: (a -> Const a b) -> s -> Const a t
  2. -> Format r (a -> r)
  3. -> Format r (s -> r)
#

Use the given lens to view an item, formatting it with the given formatter.

You can think of this as having the type:

viewed :: Lens' s a -> Format r (a -> r) -> Format r (s -> r)
Example1 expression
format (viewed _1 int) (1, "hello")"1"

This is useful when combined with the Monoid instance for Format, because it allows us to give a data structure as an argument only once, and deconstruct it with the formatters:

data Person = Person
  { _personName :: Text
  , _personAge :: Int
  }
makeLenses ''Person

me :: Person
me = Person Alex 38

format ("The person's name is " % squoted (viewed personName text) % ", and their age is " <> viewed personAge int) me
"The person's name is Alex, and their age is 38"
valueaccessed :: (s -> a) -> Format r (a -> r) -> Format r (s -> r)
#

Access an element of the structure and format it with the given formatter.

Example1 expression
format (accessed fst int) (1, "hello")"1"

Repeating the example from viewed:

format ("The person's name is " % squoted (accessed _personName text) % ", and their age is " <> accessed _personAge int) me "The person's name is Alex, and their age is 38"

Fixed-width number formatting

3 declarations
valuebinPrefix :: Integral a => Int64 -> Format r (a -> r)
#

Render an integer using binary notation with a leading 0b, padding with zeroes to the given width:

Example1 expression
format (binPrefix 16) 4097"0b0001000000000001"
valueoctPrefix :: Integral a => Int64 -> Format r (a -> r)
#

Render an integer using octal notation with a leading 0o, padding with zeroes to the given width:

Example1 expression
format (octPrefix 16) 4097"0o0000000000010001"
valuehexPrefix :: Integral a => Int64 -> Format r (a -> r)
#

Render an integer using octal notation with a leading 0x, padding with zeroes to the given width:

Example1 expression
format (hexPrefix 16) 4097"0x0000000000001001"