Muhammad Usman
Muhammad Usman

Reputation: 115

Taking sum of list in Haskell

I am trying to take the sum of a list in Haskell but it gives the error, please see the below code.

binListToDec :: [Int] -> Int
binListToDec (x:xs) = if length binListToDec == 0 then 1
                      else x + binListToDec xs

It gives the following error

 * No instance for (Foldable ((->) [Int]))
        arising from a use of `length'
    * In the first argument of `(==)', namely `length binListToDec'
      In the expression: length binListToDec == 0
      In the expression:
        if length binListToDec == 0 then 1 else x + binListToDec xs
  |
2 | binListToDec (x:xs) = if length binListToDec == 0 then 1

Upvotes: 1

Views: 4723

Answers (1)

chepner
chepner

Reputation: 532268

Among the myriad ways you could write this, two possibilities would be

binListToDec xs = if length xs == 0 then 0  -- see below
                  else (head xs) + binListToDec (tail xs)

and

binListToDec [] = 0
binListToDec (x:xs) = x + binListToDec xs

You appear to be trying to combine bits of each. There's no way to write a single pattern that matches simultaneously 1) an empty list and 2) a non-empty list with 3) its head and tail matched separately.

  • xs matches 1) and 2).
  • all@(x:xs) matches 2) and 3)
  • 1) and 3) cannot be matched, because the pairing is nonsensical: an empty list doesn't have a separate head and tail. [] and (x:xs) match lists from two non-overlapping sets of possible list values.

    Update: there is a lazy pattern match all@(~(x:xs)). The tilde prevents the match (x:xs) from being attempted until there is a need to evaluate x or xs. We think of

    binListToDec all@(~(x:xs)) = if length all == 0 then 0 else x + binListToDec
    

    as equivalent to

    binListToDec all = if length all == 0 
                       then 0
                       else let (x:xs) = all 
                            in x + binListToDec
    

    A lazy pattern match can still fail, but here we defer using x and xs until we know it won't.


length binListToDec attempts to compute the length of the function itself, not the length of its argument, in your attempt. The correct argument for length is used above. Also, the generally accepted sum of an empty list is 0, not 1.

Upvotes: 3

Related Questions