{-| Pretty runtime error messages These functions can be used to raise clear, understandable error messages for when your program violates an invariant at runtime. In particular, 'assertRight' handles a common case where we "know" that a particular 'Either' is going to be 'Right', and so we want to be able to unpack the value but also provide a high-quality error message if the value does somehow turn out to be a 'Left'. -} module PrettyError ( assertRight , fromRight , ppText , prettyError ) where import BasicPrelude import Data.ByteString.Char8 (pack) import Text.Show.Pretty (ppShow) -- | Assert that value is 'Right'. Throw error if it's 'Left'. -- -- The first argument is a message which can be used to explain why this -- error should not have happened. -- -- Use 'fromRight' if you don't want to provide a message. -- -- >>> assertRight "Artificial example" (Right 5) -- 5 -- -- >>> assertRight "Artificial example" (Left "error message") -- *** Exception: Artificial example: "error message" assertRight :: Show a => Text -- ^ A message describing the assertion -> Either a b -- ^ The 'Either' to unpack -> b -- ^ The unpacked 'Right' value assertRight _ (Right r) = r assertRight message (Left e) = terror $ message ++ ": " ++ ppText e -- | Extract the value out of a 'Right', or throw an error from a 'Left' -- made up of the pretty-printed 'Left' value. -- -- Most of the time you should use 'assertRight', since that allows you to -- provide a message, which will help to debug the problem. -- -- >>> fromRight (Right 5) -- 5 -- -- >>> fromRight (Left 4) -- *** Exception: 4 fromRight :: Show a => Either a b -> b fromRight (Left e) = prettyError e fromRight (Right r) = r -- | Pretty print a variable to 'Text' -- -- Although not strictly related to error messages, this is a handy function -- to have around if you are using "Text.Show.Pretty" and 'OverloadedStrings'. ppText :: Show a => a -> Text ppText = decodeUtf8 . pack . ppShow -- | Raise an error with a pretty-printed value. -- -- >>> prettyError ["foo","bar","baz"] -- *** Exception: [ "foo" , "bar" , "baz" ] prettyError :: Show a => a -> b prettyError = error . ppShow