We have a function that sums a list of items by their .cost values. We want to use it to sum another list of items with .cost, but the items are different types.

Is there a way to write annotations to match “anything with this type of field”?

type alias Foo = { cost : Int }
type alias Bar = { cost : Int, isIron : Bool }

sumItems : List Foo -> Int
sumItems items =
    List.foldl (\x acc -> x.cost + acc) 0 items

fooSum = sumItems listOfFoos
barSum = sumItems listOfBars



We can define a type that just has some fields like this.

sumItems : List ({ a | cost : Int }) -> Int
sumItems items =
    List.foldl (\x acc -> x.cost + acc) 0 items

Foo and Bar satisfy this type, so we can now reuse sumItems.


If you’re using the generic type a lot, you can still use a type alias to keep things more succinct.

This example shows how we can replace something in a list of “records with an id field” generically.

type alias WithId a = { a | id : String }

updateById : String -> (WithId a -> WithId a) -> List (WithId a) -> List (WithId a)
updateById id getNewItem list =
        (\x ->
            if == id then
                getNewItem x

See the docs for more detail on dealing with records.