Search code examples
haskellcompiler-errorspattern-matching

Haskell pattern matching on a list of lists - why doesn't this work?


I have the following definitions in my Haskell code:

-- A region has a list of squares, and a list of possible combinations of values,
-- all of which add up to the same total.
data Region = Region [Square] [[Int]] deriving (Show, Eq)

-- The total which each combination adds up to: if the list of combinations is
-- empty it is 0, otherwise it is the sum of the first combination.
total :: Region -> Int
total (Region _ []) = 0
total (Region _ [c:_]) = sum c

This code fails to compile with the following error:

* Couldn't match expected type `t0 Int' with actual type `Int'
    * In the first argument of `sum', namely `c'
      In the expression: sum c
      In an equation for `total': total (Region _ [c : _]) = sum c

I'm probably missing something very obvious here, but I don't understand why the compiler thinks the type of c is Int, when the pattern match tells it to bind c to the first element of a list of [Int]. What is going on?


Solution

  • The pattern [c:_], is short for [(c:_)], so c is the first item in the first (and only) sublist, not the first sublist. So c here is an Int, not an [Int], you should use:

    total :: Region -> Int
    total (Region _ []) = 0
    total (Region _ (c:_)) = sum c