Convert a value to a readable Text.
Examples
display 3"3"
display True"True"
:: a typeCtrl KGHC 9.10.3 · lts/ghc-9.10.x · c74966e · 2026-09-27
Moduletext-display-0.0.5.2Haskell2010
Use display to produce user-facing text
Convert a value to a readable Text.
display 3"3"
display True"True"
A typeclass for user-facing output.
displayBuilder :: a -> BuilderImplement this method to describe how to convert your value to Builder.
displayList :: [a] -> BuilderThe 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.
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 = displayListdisplayBuilder ([1,2,3] :: [Int])
→ displayBuilder @[Int] = displayBuilderList @Int
→ Default `displayList`
displayBuilder ("abc" :: [Char])
→ displayBuilder @[Char] = displayBuilderList @Char
→ Custom `displayList`displayPrec :: Int -> a -> BuilderThe 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.
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 adata 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 bCannotDisplayByteStrings => 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.CoreDisplay VoidDefined in text-display-0.0.5.2 · Data.Text.Display.CoreDisplay SomeExceptionDefined in text-display-0.0.5.2 · Data.Text.Display.CoreDisplay IOExceptionDefined in text-display-0.0.5.2 · Data.Text.Display.CoreDisplay Int16Defined in text-display-0.0.5.2 · Data.Text.Display.CoreDisplay Int32Defined in text-display-0.0.5.2 · Data.Text.Display.CoreDisplay Int64Defined in text-display-0.0.5.2 · Data.Text.Display.CoreDisplay Int8Defined in text-display-0.0.5.2 · Data.Text.Display.CoreDisplay Word16Defined in text-display-0.0.5.2 · Data.Text.Display.CoreDisplay Word32Defined in text-display-0.0.5.2 · Data.Text.Display.CoreDisplay Word64Defined in text-display-0.0.5.2 · Data.Text.Display.CoreDisplay Word8Defined in text-display-0.0.5.2 · Data.Text.Display.CoreDisplay BoolDefined in text-display-0.0.5.2 · Data.Text.Display.CoreDisplay CharDefined in text-display-0.0.5.2 · Data.Text.Display.CoredisplayList 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.
display [1, 2, 3]"[1,2,3]"
display ['h', 'e', 'l', 'l', 'o']"hello"
Display DoubleDefined in text-display-0.0.5.2 · Data.Text.Display.CoreDisplay FloatDefined in text-display-0.0.5.2 · Data.Text.Display.CoreDisplay IntDefined in text-display-0.0.5.2 · Data.Text.Display.CoreDisplay WordDefined in text-display-0.0.5.2 · Data.Text.Display.CoreDisplay TextDefined in text-display-0.0.5.2 · Data.Text.Display.CoreStrict Text
Display TextDefined in text-display-0.0.5.2 · Data.Text.Display.CoreLazy Text
Display ()Defined in text-display-0.0.5.2 · Data.Text.Display.CoreRealFloat e => Display (DisplayRealFloat e)Defined in text-display-0.0.5.2 · Data.Text.Display.CoreIntegral e => Display (DisplayDecimal e)Defined in text-display-0.0.5.2 · Data.Text.Display.CoreShow e => Display (ShowInstance e)Defined in text-display-0.0.5.2 · Data.Text.Display.CoreDisplay a => Display (NonEmpty a)Defined in text-display-0.0.5.2 · Data.Text.Display.CoreDisplay a => Display (Maybe a)Defined in text-display-0.0.5.2 · Data.Text.Display.CoreDisplay 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.GenericWe 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.CoreThis 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.CoreThis wrapper allows you to rely on a pre-existing Show instance in order to derive Display from it.
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)Show a => Show (ShowInstance a)Defined in text-display-0.0.5.2 · Data.Text.Display.CoreShow e => Display (ShowInstance e)Defined in text-display-0.0.5.2 · Data.Text.Display.CoreThis wrapper allows you to create an opaque instance for your type, useful for redacting sensitive content like tokens or passwords.
data UserToken = UserToken UUID
deriving Display
via (OpaqueInstance "[REDACTED]" UserToken)display $ UserToken "7a01d2ce-31ff-11ec-8c10-5405db82c3cd"
"[REDACTED]"Opaque aKnownSymbol str => Display (OpaqueInstance str a)Defined in text-display-0.0.5.2 · Data.Text.Display.CoreThis wrapper allows you to create an opaque instance for your type, useful for redacting sensitive content like tokens or passwords.
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.
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 PasswordMyRecord
{ fieldA = hello
, fieldB = Just world
, fieldC = 22
, pword = [REDACTED]
}Generic a => Generic (RecordInstance a)Defined in text-display-0.0.5.2 · Data.Text.Display.Generic(AssertNoSumRecordInstance Display a, Generic a, GDisplay1 (Rep a)) => Display (RecordInstance a)Defined in text-display-0.0.5.2 · Data.Text.Display.GenericWe 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.
type Rep (RecordInstance a) = Rep aDefined in text-display-0.0.5.2 · Data.Text.Display.GenericA 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.
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.
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.
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.