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

Moduletext-display-0.0.5.2Haskell2010

Data.Text.Display

Use display to produce user-facing text

  • 3 types
  • 1 class
  • 2 values

Documentation

2 declarations
valuedisplay :: Display a => a -> Text
#

Convert a value to a readable Text.

Examples
Example1 expression
display 3"3"
Example1 expression
display True"True"
classclass Display a where
#

A typeclass for user-facing output.

Methods

  • displayBuilder :: a -> Builder

    Implement this method to describe how to convert your value to Builder.

  • displayList :: [a] -> Builder

    The method displayList is provided to allow for a specialised way to render lists of a certain value. This is used to render the list of Char as a string of characters enclosed in double quotes, rather than between square brackets and separated by commas.

    Example
    import qualified Data.Text.Lazy.Builder as TB
    
    instance Display Char where
      displayBuilder c = TB.fromText $ T.singleton c
      displayList cs = TB.fromText $ T.pack cs
    
    instance (Display a) => Display [a] where
      -- In this instance, 'displayBuilder' is defined in terms of 'displayList', which for most types
      -- is defined as the default written in the class declaration.
      -- But when a ~ Char, there is an explicit implementation that is selected instead, which
      -- provides the rendering of the character string between double quotes.
      displayBuilder = displayList
    How implementations are selected
    displayBuilder ([1,2,3] :: [Int])
    → displayBuilder @[Int] = displayBuilderList @Int
    → Default `displayList`
    
    displayBuilder ("abc" :: [Char])
    → displayBuilder @[Char] = displayBuilderList @Char
    → Custom `displayList`
  • displayPrec :: Int -> a -> Builder

    The method displayPrec allows you to write instances that require nesting. The precedence parameter can be thought of as a suggestion coming from the surrounding context for how tightly to bind. If the precedence parameter is higher than the precedence of the operator (or constructor, function, etc.) being displayed, then that suggests that the output will need to be surrounded in parentheses in order to bind tightly enough (see displayParen).

    For example, if an operator constructor is being displayed, then the precedence requirement for its arguments will be the precedence of the operator. Meaning, if the argument binds looser than the surrounding operator, then it will require parentheses.

    Note that function/constructor application has an effective precedence of 10.

    Examples
    instance (Display a) => Display (Maybe a) where
      -- In this instance, we define 'displayPrec' rather than 'displayBuilder' as we need to decide
      -- whether or not to surround ourselves in parentheses based on the surrounding context.
      -- If the precedence parameter is higher than 10 (the precedence of constructor application)
      -- then we indeed need to surround ourselves in parentheses to avoid malformed outputs
      -- such as @Just Just 5@.
      -- We then set the precedence parameter of the inner 'displayPrec' to 11, as even
      -- constructor application is not strong enough to avoid parentheses.
      displayPrec _ Nothing = "Nothing"
      displayPrec prec (Just a) = displayParen (prec > 10) $ "Just " <> displayPrec 11 a
    data Pair a b = a :*: b
    infix 5 :*: -- arbitrary choice of precedence
    instance (Display a, Display b) => Display (Pair a b) where
      displayPrec prec (a :*: b) = displayParen (prec > 5) $ displayPrec 6 a <> " :*: " <> displayPrec 6 b
Instances35Display, …
  • CannotDisplayByteStrings => Display ByteStringDefined in text-display-0.0.5.2 · Data.Text.Display.Core

    🚫 You should not try to display strict ByteStrings!

    💡 Always provide an explicit encoding. Use decodeUtf8' or decodeUtf8With to convert from UTF-8

  • CannotDisplayByteStrings => Display ByteStringDefined in text-display-0.0.5.2 · Data.Text.Display.Core

    🚫 You should not try to display lazy ByteStrings!

    💡 Always provide an explicit encoding. Use decodeUtf8' or decodeUtf8With to convert from UTF-8

  • Display IntegerDefined in text-display-0.0.5.2 · Data.Text.Display.Core
  • Display VoidDefined in text-display-0.0.5.2 · Data.Text.Display.Core
  • Display SomeExceptionDefined in text-display-0.0.5.2 · Data.Text.Display.Core
  • Display IOExceptionDefined in text-display-0.0.5.2 · Data.Text.Display.Core
  • Display Int16Defined in text-display-0.0.5.2 · Data.Text.Display.Core
  • Display Int32Defined in text-display-0.0.5.2 · Data.Text.Display.Core
  • Display Int64Defined in text-display-0.0.5.2 · Data.Text.Display.Core
  • Display Int8Defined in text-display-0.0.5.2 · Data.Text.Display.Core
  • Display Word16Defined in text-display-0.0.5.2 · Data.Text.Display.Core
  • Display Word32Defined in text-display-0.0.5.2 · Data.Text.Display.Core
  • Display Word64Defined in text-display-0.0.5.2 · Data.Text.Display.Core
  • Display Word8Defined in text-display-0.0.5.2 · Data.Text.Display.Core
  • Display BoolDefined in text-display-0.0.5.2 · Data.Text.Display.Core
  • Display CharDefined in text-display-0.0.5.2 · Data.Text.Display.Core

    displayList is overloaded, so that when the Display [a] instance calls displayList, we end up with a nice string instead of a list of chars between brackets.

    Example1 expression
    display [1, 2, 3]"[1,2,3]"
    Example1 expression
    display ['h', 'e', 'l', 'l', 'o']"hello"
  • Display DoubleDefined in text-display-0.0.5.2 · Data.Text.Display.Core
  • Display FloatDefined in text-display-0.0.5.2 · Data.Text.Display.Core
  • Display IntDefined in text-display-0.0.5.2 · Data.Text.Display.Core
  • Display WordDefined in text-display-0.0.5.2 · Data.Text.Display.Core
  • Display TextDefined in text-display-0.0.5.2 · Data.Text.Display.Core

    Strict Text

  • Display TextDefined in text-display-0.0.5.2 · Data.Text.Display.Core

    Lazy Text

  • Display ()Defined in text-display-0.0.5.2 · Data.Text.Display.Core
  • RealFloat e => Display (DisplayRealFloat e)Defined in text-display-0.0.5.2 · Data.Text.Display.Core
  • Integral e => Display (DisplayDecimal e)Defined in text-display-0.0.5.2 · Data.Text.Display.Core
  • Show e => Display (ShowInstance e)Defined in text-display-0.0.5.2 · Data.Text.Display.Core

    This wrapper allows you to rely on a pre-existing Show instance in order to derive Display from it.

  • Display a => Display (NonEmpty a)Defined in text-display-0.0.5.2 · Data.Text.Display.Core
  • Display a => Display (Maybe a)Defined in text-display-0.0.5.2 · Data.Text.Display.Core
  • Display a => Display [a]Defined in text-display-0.0.5.2 · Data.Text.Display.Core
  • (AssertNoSumRecordInstance Display a, Generic a, GDisplay1 (Rep a)) => Display (RecordInstance a)Defined in text-display-0.0.5.2 · Data.Text.Display.Generic

    We leverage the AssertNoSum type family to prevent consumers from deriving instances for sum types. Sum types should use a manual instance or derive one via ShowInstance.

  • KnownSymbol str => Display (OpaqueInstance str a)Defined in text-display-0.0.5.2 · Data.Text.Display.Core

    This wrapper allows you to create an opaque instance for your type, useful for redacting sensitive content like tokens or passwords.

  • CannotDisplayBareFunctions => Display (a -> b)Defined in text-display-0.0.5.2 · Data.Text.Display.Core

    🚫 You should not try to display functions!

    💡 Write a newtype wrapper that represents your domain more accurately. If you are not consciously trying to use display on a function, make sure that you are not missing an argument somewhere.

  • (Display a, Display b) => Display (a, b)Defined in text-display-0.0.5.2 · Data.Text.Display.Core
  • (Display a, Display b, Display c) => Display (a, b, c)Defined in text-display-0.0.5.2 · Data.Text.Display.Core
  • (Display a, Display b, Display c, Display d) => Display (a, b, c, d)Defined in text-display-0.0.5.2 · Data.Text.Display.Core

Deriving your instance automatically

3 declarations
newtypenewtype ShowInstance a
#

This wrapper allows you to rely on a pre-existing Show instance in order to derive Display from it.

Example
data AutomaticallyDerived = AD
 -- We derive 'Show'
 deriving stock Show
 -- We take advantage of the 'Show' instance to derive 'Display' from it
 deriving Display
   via (ShowInstance AutomaticallyDerived)

Constructors

Instances2Show, Display
  • Show a => Show (ShowInstance a)Defined in text-display-0.0.5.2 · Data.Text.Display.Core
  • Show e => Display (ShowInstance e)Defined in text-display-0.0.5.2 · Data.Text.Display.Core

    This wrapper allows you to rely on a pre-existing Show instance in order to derive Display from it.

newtypenewtype OpaqueInstance (str :: Symbol) a
#

This wrapper allows you to create an opaque instance for your type, useful for redacting sensitive content like tokens or passwords.

Example
data UserToken = UserToken UUID
 deriving Display
   via (OpaqueInstance "[REDACTED]" UserToken)
display $ UserToken "7a01d2ce-31ff-11ec-8c10-5405db82c3cd"
"[REDACTED]"

Constructors

Instances1Display
  • KnownSymbol str => Display (OpaqueInstance str a)Defined in text-display-0.0.5.2 · Data.Text.Display.Core

    This wrapper allows you to create an opaque instance for your type, useful for redacting sensitive content like tokens or passwords.

newtypenewtype RecordInstance a
#

This wrapper allows you to create an Display instance for a record, so long as all the record fields have a Display instance as well.

Example
data Password = Password
 deriving Display
   via (OpaqueInstance "[REDACTED]" Password)
data MyRecord =
   MyRecord
     { fieldA :: String
     , fieldB :: Maybe String
     , fieldC :: Int
     , pword :: Password
     }
     deriving stock (Generic)
     deriving (Display) via (RecordInstance MyRecord)
putStrLn . Data.Text.unpack . display $ MyRecord "hello" (Just "world") 22 Password
MyRecord
  { fieldA = hello
  , fieldB = Just world
  , fieldC = 22
  , pword = [REDACTED]
  }
Instances3Generic, Display, Rep

Writing your instance by hand

1 declaration
valuedisplayParen :: Bool -> Builder -> Builder
#

A utility function that surrounds the given Builder with parentheses when the Bool parameter is True. Useful for writing instances that may require nesting. See the displayPrec documentation for more information.

Design choices

0 declarations
A “Lawless Typeclass”

The Display typeclass does not contain any law. This is a controversial choice for some people, but the truth is that there are not any laws to ask of the consumer that are not already enforced by the type system and the internals of the Text type.

"🚫 You should not try to display functions!"

Sometimes, when using the library, you may encounter this message:

• 🚫 You should not try to display functions!
  💡 Write a 'newtype' wrapper that represents your domain more accurately.
     If you are not consciously trying to use `display` on a function,
     make sure that you are not missing an argument somewhere.

The display library does not allow the definition and usage of Display on bare function types ((a -> b)). Experience and time have shown that due to partial application being baked in the language, many users encounter a partial application-related error message when a simple missing argument to a function is the root cause.

There may be legitimate uses of a Display instance on a function type. But these usages are extremely dependent on their domain of application. That is why it is best to wrap them in a newtype that can better express and enforce the domain.

"🚫 You should not try to display ByteStrings!"

An arbitrary ByteStrings cannot be safely converted to text without prior knowledge of its encoding.

As such, in order to avoid dangerously blind conversions, it is recommended to use a specialised function such as decodeUtf8' or decodeUtf8With if you wish to turn a UTF8-encoded ByteString to Text.