A list of Records, how to count a total sum of a certain field

Hello everybody! I have a list of records and I would like to count the total sum of a certain field. I’m using a following type alias:

type alias LimitType =
{ limitType : String
, baseLimit : Float
, extraLimit : Float
, extraExpires : Date
}

and I would like to write a function which counts the total sum of baseLimit fields and produces a Float:

sumBaseLimits : List LimitType -> Float

but I just can’t wrap my head around hoe to actually do it. I played around with dict and foldl but I’m quite unsure if that is the way to go.
I really appreciate any help with this matter!

Hi @myasmy!

What you probably want is to use the List.sum function

sumBaseLimits : List LimitType -> Float
sumBaseLimits items =
  List.sum items

If you try this, you’ll notice this doesn’t work, because List.sum takes a list of numbers (integers or floats), and we’re giving it a List LimitType. To make it work, you’ll want to transform the items to a List Float before summing it. We’ll use List.map for that. You give it a function on how to transform an item from the list to something else. Here, we’ll just take the value of the baseLimit field

sumBaseLimits : List LimitType -> Float
sumBaseLimits items =
  List.sum (List.map (\item -> item.baseLimit) items)

And this should work.

Just FYI, a shorter/nicer way to write this could be the following (it does exactly the same thing)

sumBaseLimits : List LimitType -> Float
sumBaseLimits items =
  items
    |> List.map .baseLimit
    |> List.sum

For questions like these, you’re likely to get faster answers (or easier back and forth questions) on Slack at http://elmlang.herokuapp.com/. Check out the #beginners or #help channels to ask your question :slight_smile:

I hope this helped!

5 Likes

For a point-free style you could do:

sumBaseLimits : List LimitType -> Float
sumBaseLimits =
  List.map .baseLimit >> List.sum
2 Likes

I played around with dict and foldl but I’m quite unsure if that is the way to go.

You could have done it using List.foldl, it would look something like this

sumBaseLimits : List LimitType -> Float
sumBaseLimits items =
  List.foldl
    (\item sum -> sum + item.baseLimit)
    0
    items
3 Likes

Just for completeness, and because recursion is a useful tool to have in your toolbox, here’s a recursive version:

sumBaseLimits : List LimitType -> Float
sumBaseLimits limitTypes =
    case limitTypes of
        [] ->
            -- the sum of base limits of an empty list is zero
            0

        first :: rest ->
            -- otherwise, the sum is the first item's base limit
            -- plus the sum of base limits of the rest of the list
            first.baseLimit + sumBaseLimits rest

Unfortunately, this version will result in a stack overflow on large lists. You can fix the problem by making the function tail recursive; this next version you’d call as sumBaseLimits limitTypes 0:

sumBaseLimits : List LimitType -> Float -> Float
sumBaseLimits limitTypes sumSoFar =
    case limitTypes of
        [] ->
            -- no more items to process, return the sum so far
            sumSoFar

        first :: rest ->
            -- add the current item's base limit to our
            -- sum so far and then continue with the rest
            sumBaseLimits rest (sumSoFar + first.baseLimit)

The tail recursive version should be the fastest of all the approaches, but that’s only likely to be important if you’re dealing with very large lists (many thousands of elements) or processing a lot of smaller lists.

4 Likes

Thank you all so much!
And special thanks that you provided so clear explanations and links for further reading, not only the answers.
I’ll definitely check out Elm Slack also!

2 Likes

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.