1
votes

Working on my model. I've made a type to hold a list of my items:

type alias Item =
    { id : ItemId
    , containerId : ItemId
    , title : String
    , children : Items
    }


type Items
    = Items (List Item)

findByTitle : String -> Items -> Items
findByTitle title (Items items) =
    List.filter (\item -> item.title == title) items
The definition of `findByTitle` does not match its type annotation.
The type annotation for `findByTitle` says it always returns:
    Items
But the returned value (shown above) is a:
    List { children : Items, containerId : ItemId, id : ItemId, title : String }

The 2nd argument to function getItemById is causing a mismatch. Function getItemById is expecting the 2nd argument to be: Items But it is: List Item

getAllContainers : Item -> Items -> Items
getAllContainers item (Items items) =
    let
        container =
            (getItemById item.containerId items)  -- error below
    in
        case container of
            Nothing ->
                --  We assume that if a container is not in the list, it must be the root
                []

            Just containerItem ->
                containerItem :: getAllContainers containerItem items


getItemById : ItemId -> Items -> Maybe Item
getItemById id (Items items) =
    List.filter (\item -> id == item.id) items
        |> List.head
The 2nd argument to function `getItemById` is causing a mismatch.
Function `getItemById` is expecting the 2nd argument to be:
    Items
But it is:
    List Item
    
1

1 Answers

3
votes

You can get the true list by pattern matching to expose the inner list. Here is an example of this concept occurring in a top level function:

myFunc : Items -> Html msg
myFunc (Items innerItems) =
    List.map func innerItems

edit

For your supplied function, if you are returning Items, you will need to "wrap" the list of items back up in the Items constructor:

findByTitle : String -> Items -> Items
findByTitle title (Items items) =
    Items (List.filter (\item -> item.title == title) items)