Search code examples
listhaskellnon-exhaustive-patterns

How to detect the end of a list in Haskell?


I'm writting a recursive function that use specific formulas to calculate 2 lists. But I will simplify the function so you can understand the problem I'm having because the point here is to detect [] of the list.

So I've the following code:

listSum::([Integer],[Integer])->Double
listSum ((x:xs),(y:ys)) 
    | ((x:xs),(y:ys))==(x:[],y:[])=0.0
    | otherwise = (((fromIntegral x)::Double)+((fromIntegral y)::Double)) + listSum ((xs),(ys))

Output I'm having right now

listSum([1,2],[1,2])
2.0

listSum([1],[1])
0.0

listSum([],[])
*** Exception: file.hs: .....: Non-exhaustive patterns in function ListSum

And the output I wish to have

listSum([1,2],[1,2])
6.0

listSum([1],[1])
2.0

listSum([],[])
0.0

What did I miss? Or did I write too much?


Solution

  • You don't need the first guard in your function. You can simply write it as the following (I just dropped ::Double because Haskell can infer it)

    listSum :: ([Integer], [Integer]) -> Double
    listSum ([], []) = 0.0
    listSum ((x:xs),(y:ys)) = fromIntegral x + fromIntegral y + listSum (xs, ys)
    

    Now, whenever the arguments passed to listSum are empty lists, the result will be 0.0, otherwise the recursive function will be called.

    Note: The above function will work only if both the lists are of equal size. Otherwise, you need to write it like this

    listSum::([Integer],[Integer])->Double
    listSum ([], []) = 0.0
    listSum ((x:xs), []) = fromIntegral x + listSum(xs, [])
    listSum ([], (y:ys)) = fromIntegral y + listSum(ys, [])
    listSum ((x:xs),(y:ys)) = fromIntegral x + fromIntegral y + listSum (xs, ys)
    

    Note: Even simpler, the entire code can be written, as suggested by Rein Henrichs, like this

    pairwiseSum xs ys = sum (zipWith (+) xs ys)