0

I'm learning list operations in Haskell and now I'm trying out various list operations on Maybe list type. Currently, I have this implementation of sum of elements in list in Haskell

sum :: Num a => [a] -> a sum [] = 0 sum (a:t) = a + sum t 

Now I want to do the same thing but instead of returning the value, I want to return a Maybe type instead. And when the list given is empty it should return Nothing.

I've come up with this

sum :: Num a => [a] -> Maybe a sum [] = Nothing sum (a:t) = fmap (a+) (sum t) 

But the result of all non empty list given results in Nothing.

From what I understand, the list given will eventually pattern match with the empty list therefore returning Nothing.

How do I fix this so that it returns the expected value and of Maybe type. I can't figure out how to make it work recursively as the normal sum implementation above, so I guess there should be another way. Would prefer if only Prelude module is imported as I'm still trying to absorb stuff inside the Prelude module.

1
  • Note that the correct sum of an empty list is 0, so your sum function is actually wrong. It doesn't not exist - it's 0. Commented Sep 17, 2020 at 12:58

1 Answer 1

7

The problem is that your recursive function always uses the empty list as a base case, so your base case value is always Nothing. You only want to return Nothing if the "root" call takes an empty list. Otherwise, you want to use the singleton list as your base case.

sum :: Num a => [a] -> Maybe a sum [] = Nothing sum [x] = Just x sum (a:t) = fmap (a+) (sum t)

This way, sum [] will never be reached by a recursive call; any non-empty list will hit the base case sum [x] first.

Another way to organize this is to use your original total function as a helper that sums non-empty lists only, and handle the empty list separately.

sum :: Num a => [a] -> Maybe a sum [] = Nothing sum xs = sum' xs where sum' [] = Just 0 sum' (a:t) = fmap (a+) (sum' t) 

Note that sum' can be called on an empty list, but only if it is originally called on a non-empty list.

As @chi points out, the helper function doesn't need to use Maybe at all; since it only sums non-empty lists, you can skip using fmap and sum the list normally; only the final result needs to be wrapped in Just:

sum :: Num a => [a] -> Maybe a sum [] = Nothing sum xs = Just (sum' xs) where sum' [] = 0 sum' (a:t) = a + sum' t 
Sign up to request clarification or add additional context in comments.

2 Comments

In the last example we can also lift Just outside the recursion as in sum [] = Nothing ; sum xs = Just (sum' xs) where sum' [] = 0 ; sum' (a:t) = a + sum' t. This avoids fmap, so it perhaps less useful as a teaching exercise.
@chi That's probably actually clearer, as it emphasizes that the Maybe wrapper only applies to the final sum of a non-empty original argument.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.