Search code examples
haskellguard

Error in guard condition while combining a list and single item


I am trying to add the head of the list (r) to the list sack, however I keep getting this error message.

ERROR "Knapsack.hs":35 - Type error in guarded expression
*** Term           : findItems rt (r : sack) (getTotalWeight sack r)
*** Type           : [Item]
*** Does not match : [[Item]]

The code is listed below.

findItems :: [Item] -> [Item] -> Float -> [Item]
findItems (r:rt) sack total 
            | total > 20 = [sack]
            | canContinue = findItems rt (r : sack ) (getTotalWeight sack r) 
            | otherwise = [sack] 
            where canContinue = (getTotalWeight sack r) < 20 

Solution

  • You cannot return [sack] from findItems, because sack is already of type [Item], so [sack] is of type [[Item]]. Remove the brackets.

    The reason the message complains about the second case (which does return [Item] as it should) is probably (I'm guessing here) that Haskell expects all cases to be of the same type, so it checks that they're all of the same type as the first, which incorrectly happens to be [[Item]]. This checking appears to happen before it even tries to reconcile the type of the | expression with the type of findItems. Haskell gurus will probably be able to correct me on the finer points here :)