Search code examples
elm

How do you iterate a List (Maybe a)


I have the following graphQL result:

[Just { details = Just "Engine failure at 33 seconds and loss of vehicle", launch_year = Just "2006", links = Just { article_link = Just "https://www.space.com/2196-spacex-inaugural-falcon-1-rocket-lost-launch.html" }, mission_name = Just "FalconSat" }]

Based on the following types:

type alias Launch =
    { mission_name : Maybe String
    , details : Maybe String
    , launch_year : Maybe String
    , links : Maybe LaunchLinks
    }


type alias Launches =
    Maybe (List (Maybe Launch))


type alias LaunchLinks =
    { article_link : Maybe String
    }

I want to List.map through and display the results in unordered list. I started with this:

renderLaunch : Launches -> Html Msg
renderLaunch launches =
    div [] <|
        case launches of
            Nothing ->
                [ text "Nothing here" ]

            Just launch ->
                launch
                    |> List.map (\x -> x)
                    |> ul []

But I keep getting this error:

This function cannot handle the argument sent through the (|>) pipe:

141| launch 142| |> List.map (\x -> x) 143| |> ul [] ^^^^^ The argument is:

List (Maybe Launch)

But (|>) is piping it a function that expects:

List (Html msg)

Solution

  • The problem is that the Just launch case needs to result in a List (Html msg) but the code results in a different type being returned.

    When you are using List.map (\x -> x), it is essentially a no-op. You are iterating over a List (Maybe Launch) and returning the same thing. I'd recommend creating another function that takes a Maybe Launch value and use that as your mapping function. For example:

    displayLaunch : Maybe Launch -> Html Msg
    displayLaunch launch =
        case launch of
            Nothing -> text "No launch"
            Just l -> text (Debug.toString l)
    

    Now you can plug that into your mapping function:

    Just launch ->
        launch
            |> List.map displayLaunch
            |> ul []
    

    But, whoops! Now you get a new error indicating:

    The 2nd branch is:
    
        Html Msg
    
    But all the previous branches result in:
    
        List (Html msg)
    

    The problem here is that we are now returning a ul from the Just launch branch and we need to return a list of html. You can use List.singleton to create a list with just one item:

    Just launch ->
        launch
            |> List.map displayLaunch
            |> ul []
            |> List.singleton