<h2 id="initial-state">Initial state</h2>
<p>When I originally wanted a unified error reporting on the server-side, I made one huge type that enumerated all the possible error cases that could be reported:</p>
<pre><code>-- | Error codes for all errors returned by API
data ErrorCode
    -- common error codes
    = ResourceNotFound
    | InsufficientRights
    | FailedToParseDataInDatabase
    -- errors specific to news
    | SpecialEventHasAlreadyBeenResolved
    | UnsupportedArticleType
    | SpecialNewsExtractionFailed
    | TriedToMakeChoiceForRegularArticle
    -- errors specific to simulation state
    | SimulationStatusNotFound
    | DeltaTIsTooBig
    | TurnProcessingAndStateChangeDisallowed
    | SimulationNotOpenForCommands
    | SimulationNotOpenForBrowsing
    -- errors specific to people
    | StatIsTooLow Text
    | CouldNotConfirmDateOfBirth
    | DateOfBirthIsInFuture
    | FirstNameIsEmpty
    | FamilyNameIsEmpty
    | CognomenIsEmpty
    | RegnalNumberIsLessThanZero
    -- errors specific to new person creation
    | AgeBracketStartIsGreaterThanEnd
    | PersonCreationFailed
    deriving (Show, Read, Eq)
</code></pre>
<p>Then I had some helper functions to turn any value of that type into a nice error message:</p>
<pre><code>errorCodeToStatusCode :: ErrorCode -&gt; Int
statusCodeToText :: Int -&gt; ByteString
errorCodeToText :: ErrorCode -&gt; Text
raiseIfErrors :: [ErrorCode] -&gt; HandlerFor App ()
</code></pre>
<p><code>errorCodeToStatusCode</code> was responsible for turning <code>ErrorCode</code> into http status code. For example <code>StatIsTooLow "intrigue"</code> would be <code>400</code>. <code>statusCodeToText</code> would take this code and turn it into short error message given in http response. <code>400</code> would be <code>Bad Request</code>. <code>errorCodeToText</code> would give a bit more verbose explanation of what happened, <code>StatIsTooLow "intrigue"</code> would be mapped to <code>"Stat intrigue is too low"</code>. Finally <code>raiseIfErrors</code> would take a list of <code>ErrorCode</code> and use these helper functions to turn them into a http response with correct status code, error message and json body detailing all errors that had happened:</p>
<pre><code>[
    { code:
        { tag: &quot;StatIsTooLow&quot;
        , contents: &quot;intrique&quot;
        }
    , error: &quot;Stat intrigue is too low&quot;
    }
]
</code></pre>
<p>There’s two tags: <code>code</code>, which contains machine readable details about the error and <code>error</code>, which contains error message that can be shown to user.</p>
<p>While this worked fine, there was some problems with it. <code>ErrorCode</code> type was growing larger and larger and the module it was defined in was referred all over the codebase. Every time I added a new error message, all the modules that used error reporting had to be compiled and it was getting slow.</p>
<h2 id="solution">Solution</h2>
<p>Breaking up the <code>ErrorCode</code> to smaller types and moving them to different modules would means less modules were going to built when I added a new error code. The problem was that <code>raiseIfErrors :: [ErrorCode] -&gt; HandlerFor App ()</code> wanted a list of <code>ErrorCode</code> and elements in a list have to be of same type.</p>
<p>I started by splitting <code>ErrorCode</code> to smaller types. Each of the smaller error types have automatically derived toJSON and fromJSON functions for serializing them to and from JSON:</p>
<pre><code>data PersonCreationError =
    StatIsTooLow Text
    | CouldNotConfirmDateOfBirth
    | DateOfBirthIsInFuture
    | FirstNameIsEmpty
    | FamilyNameIsEmpty
    | CognomenIsEmpty
    | RegnalNumberIsLessThanZero
    deriving (Show, Read, Eq)

$(deriveJSON defaultOptions &#39;&#39;PersonCreationError)
</code></pre>
<p>That <code>$(deriveJSON defaultOptions ''PersonCreationError)</code> is template haskell call. Basically it invokes a <code>deriveJSON</code> function with <code>PersonCreationError</code> as parameter and compiles and splices the resulting code here. This is fast and easy way of generating <code>ToJSON</code> and <code>FromJSON</code> instances and avoiding having to write them by hand. It is very similar to how Lisp macros work.</p>
<p>Then I defined a type class, that has functions for getting a http status code and a error message that can be shown to user. <code>statusCodeToText</code> I could use as is, without any modifications:</p>
<pre><code>class ErrorCodeClass a where
    httpStatusCode :: a -&gt; Int
    description :: a -&gt; Text
</code></pre>
<p>I have to have instance of <code>ErrorCodeClass</code> defined for each and every smaller error type. Here’s an excerpt of <code>PersonCreationError</code> showing how it would look like:</p>
<pre><code>instance ErrorCodeClass PersonCreationError where
    httpStatusCode = \case
        StatIsTooLow _ -&gt; 400
        CouldNotConfirmDateOfBirth -&gt; 500
...

    description = \case
        StatIsTooLow s -&gt;
            &quot;Stat &quot; ++ s ++ &quot; is too low&quot;
...
</code></pre>
<p>A little note: <code>description = \case</code> relies on lambda case extension. It is just a slightly different way of writing:</p>
<pre><code>    description d =
        case d of
</code></pre>
<p>This allows me to turn values of these smaller error types into error messages that could be sent to the user.</p>
<p>The second part of the solution is to figure out a way to put values of these smaller error types into same list. If a list is of type <code>[PersonCreationError]</code>, it can’t contain values of <code>CommonError</code> and vice versa. Creating a wrapper like:</p>
<pre><code>data ECode a = ECode a
</code></pre>
<p>doesn’t work, because then I would have elements of type <code>ECode PersonCreationError</code> and <code>ECode CommonError</code>, which are of different type. What I need, is a way to wrap all these different types into a wrapper that loses the type of wrapped value. Another problem is that I need to place constraints on what kind of values can be wrapped. I need them to have instances for <code>ErrorCodeClass</code> (for getting error information) and ToJSON (for serializing them into JSON). There’s several ways of doing this, but I chose to use generalized algebraic data types (GADTs for short):</p>
<pre><code>{-# LANGUAGE GADTs #-}

data ECode where
    ECode :: (ErrorCodeClass a, ToJSON a) =&gt; a -&gt; ECode
</code></pre>
<p>Now type <code>ECode</code> has one value constructor, also named to <code>ECode</code>, which takes one parameter <code>a</code>. <code>a</code> can be anything, as long as there’s <code>ErrorCodeClass</code> and <code>ToJSON</code> instances defined for it. Calling this constructor will return <code>ECode</code>. If you compare this with the previous definition of <code>ECode</code>, you’ll notice two major differences:</p>
<ul>
<li><code>a</code> is constrained to have specific type class instances</li>
<li>resulting type is <code>ECode</code>, not <code>ECode a</code></li>
</ul>
<p>The second part means that I can wrap different types into <code>ECode</code> and place them into a same list without problems. Type of that list is simply <code>[ECode]</code>.</p>
<p>But having a list of error codes wrapped in <code>ECode</code> isn’t going to do much to us. We need to be able to turn them into http status code, text and list of error messages. Luckily we have a type class just for that:</p>
<pre><code>instance ErrorCodeClass ECode where
    httpStatusCode (ECode a) =
        httpStatusCode a

    description (ECode a) =
        description a
</code></pre>
<p><code>httpStatusCode</code> of <code>ECode</code> is <code>httpStatusCode</code> of the value <code>ECode</code> wraps. Similarly <code>description</code> of <code>ECode</code> is <code>description</code> of the wrapped value.</p>
<p>For turning <code>ECode</code> into JSON, I opted for hand written instance:</p>
<pre><code>instance ToJSON ECode where
    toJSON (ECode a) =
        object [ &quot;HttpCode&quot; .= httpStatusCode a
               , &quot;FaultCode&quot; .= toJSON a
               , &quot;ErrorDescription&quot; .= description a
               ]
</code></pre>
<p>This gives me complete control over how I want to report errors to the client.</p>
<p>Final piece of the puzzle is <code>raiseIfErrors</code> function:</p>
<pre><code>raiseIfErrors :: [ECode] -&gt; HandlerFor App ()
raiseIfErrors errors = do
    when (not $ null errors) $ do
        let code = fromMaybe 500 $ errors ^? ix 0 . to httpStatusCode
        let msg = statusCodeToText code
        sendStatusJSON (Status code msg) $ toJSON errors
</code></pre>
<p>If there are any elements in the passed in list, grab the http status code and text from the first element of the list. I was considering writing some sort of logic to deduce which error code to return in case there are more than one type in the list, but decided against it. There doesn’t seem to be any easy way to decide between HTTP 400 Bad Request and HTTP 500 Internal Server Error. So I just return the first one. Body of the response contains list of errors codes:</p>
<pre><code>[
    { HttpCode: 400
    , FaultCode: {
        Tag: &quot;StatIsTooLow&quot;
        , Contents: &quot;intrique&quot;
        }
    , ErrorDescription: &quot;Stat intrigue is too low&quot;
    }
]
</code></pre>
<p>Since manually wrapping things in <code>ECode</code> gets tedious after a while, I defined function for each type of error that does that for me:</p>
<pre><code>statIsTooLow :: Text -&gt; ECode
statIsTooLow s = ECode $ StatIsTooLow s
</code></pre>
<p>Now, instead of writing <code>ECode $ StatIsTooLow "intrigue"</code>, I can write <code>statIsTooLow "intrigue"</code>. And if I ever decide to change internals of errors again, I can change how these functions are defined and hopefully don’t have to change each and every place where they’re being used.</p>
<h2 id="different-solution">Different solution</h2>
<p>Another way to tackle this problem is to use records instead of algebraic data types:</p>
<pre><code>data ECode = ECode
    { httpCode :: Int
    , description :: Text
    }

statIsTooLow :: Text -&gt; ECode
statIsTooLow s =
    ECode
    { httpCode = 400
    , description = &quot;Stat &quot; ++ s ++ &quot; is too low&quot;
    }
</code></pre>
