Buda Gavril
Buda Gavril

Reputation: 21637

elm: get first error message from a list

Giving the model (related to this):

type alias ValidationResult =
    { parameter : String
    , errorMessage : String
    }


type alias ErrorResponse =
    { validationErrors : List ValidationResult }


decodeValidationResults : Decoder ValidationResult
decodeValidationResults =
  map2 ValidationResult
    (field "Parameter" string)
    (field "ErrorMessage" string)

decodeErrorResponse : Decoder ErrorResponse
decodeErrorResponse =
    map ErrorResponse
        (field "ValidationErrors" (list decodeValidationResults))

I want to create a function that returns the forst error message from the ErrorResponse. Here is what I've tried:

firstErrorMessage : Decoder CardEngineErrorResponse -> String
firstErrorMessage decoder response =
    case List.head response.validationErrors of
        Just something ->
            something.errorMessage

        Nothing ->
            toString ""

But I'm getting the error:

The definition of `firstErrorMessage` does not match its type annotation.

The type annotation for `firstErrorMessage` says it always returns:
 
     String
 
 But the returned value (shown above) is a:
 
     { b | validationErrors : List { a | errorMessage : String } } -> String
 
 Hint: It looks like a function needs 1 more argument.

Any of you have any idea what I am doing wrong?

Upvotes: 0

Views: 104

Answers (1)

Chad Gilbert
Chad Gilbert

Reputation: 36375

If you are just trying to get the first error message from an ErrorResponse value, you don't need to reference Decoder:

firstErrorMessage : ErrorResponse -> String
firstErrorMessage response =
    case List.head response.validationErrors of
        Just something ->
            something.errorMessage

        Nothing ->
            ""

or, more succinctly:

firstErrorMessage : ErrorResponse -> String
firstErrorMessage response =
    List.head response.validationErrors
        |> Maybe.map .errorMessage
        |> Maybe.withDefault ""

If you are instead trying to do this all within context of a decoder, you can do so using Json.Decode.map:

firstErrorMessageDecoder : Decoder String
firstErrorMessageDecoder =
    decodeErrorResponse
        |> map firstErrorMessage

One more note: When something has the possibility of failing, it is often best to retain the notion of Maybe. Instead of defaulting to the empty string which callers will have to know about, you can build a stronger API by returning a Maybe String:

firstErrorMessage : ErrorResponse -> Maybe String
firstErrorMessage response =
    List.head response.validationErrors
        |> Maybe.map .errorMessage

Upvotes: 2

Related Questions