Reputation: 115
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
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