Search code examples
listsortingfunctional-programmingelm

"This is not a record"-Error when trying to sort a list


I want to sort my list descended but when I use the keyword .sort I get an error:

This is not a record, so it has no fields to access!

106| { model | teams = List.sort.map (\p -> {p | activated = True}) model.teams, activatedOutput = True} ^^^^^^^^^ This sort value is a:

List comparable -> List comparable

But I need a record with a map field!

This is the line I have modified and with which I want to sort the list.

Submit -> 
      { model | teams = List.sort.map (\p -> {p | activated = True}) model.teams, activatedOutput = True} 

Solution

  • .sort is not a keyword, it is a function inside the List module. There are several types of sorting function.

    The signature of sort is:

    sort : List comparable -> List comparable
    

    Which means that the values in the lists themselves have to be comparable which has special meaning in Elm. Specifically, only built-in things like numbers and strings are comparable. Custom types are not comparable, and neither are booleans.

    It may sound strange to hear that booleans do not fit the comparable classification but consider this: What does it mean to ask the question, is True greater than or less than False in every scenario? Rather, you'll have to come up with your own definition of how to sort your custom object.

    And for that, we can use the List.sortBy function, which has this signature:

    sortBy : (a -> comparable) -> List a -> List a
    

    This can sort a list of anything, as long as you provide a function that defines how to sort the thing.

    So if you want those teams where activated is True to be shown at the top, you can use this for sorting:

    List.sortBy (\x -> if x.activated then 0 else 1) model.teams
    

    Whereas if you want teams where activated is False to be at the top, you can use this:

    List.sortBy (\x -> if x.activated then 1 else 0) model.teams