0
\$\begingroup\$

I have a function that will calculate the sum of a list of integer, however if any of the number is negative, it will should an error instead (not throwing exception).

The following is a working Haskell code (Glasgow Haskell Compiler, Version 7.10.3):

addAll :: [Int] -> Either String Int                                                                                                                          
addAll xs = foldl safeAdd (Right 0) xs                                                                                                                        
   where                                                                                                                                                     
     safeAdd :: Either String Int -> Int -> Either String Int                                                                                              
     safeAdd = (\acc next -> case acc of                                                                                                                   
                     Left s  -> Left s                                                                                                                     
                     Right n -> if next < 0                                                                                                                
                                 then Left (show next ++ " is not positive")                                                                               
                                 else Right (n + next))

Examples output of the function:

addAll [1,2,3]  -- Right 6
addAll [-1,2,3] -- Left "-1 is not positive"

Although the code works, but I'm not entirely satisfied with it, because the recursion keeps going until the last element even though errors are encountered early. Not only that, it feels a little more complicated than it should be.

After reading some SO posts such as this one, I think that the code above can be further simplified using functions like foldM or even applicative <$>.

But, I'm just not sure how to use those functions, so please do show me a way to simplify the code above.

\$\endgroup\$
1
\$\begingroup\$
import Data.Foldable

addAll :: [Int] -> Either String Int                                                                                                                          
addAll = foldlM safeAdd 0 where
  safeAdd :: Int -> Int -> Either String Int
  safeAdd n next = if next < 0
    then Left (show next ++ " is not positive")
    else Right (n + next)

Refer http://hackage.haskell.org/package/base-4.12.0.0/docs/Data-Foldable.html#v:foldlM

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.