Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 9269603
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 18, 20262026-06-18T15:09:56+00:00 2026-06-18T15:09:56+00:00

Based on SO question 13350164 How do I test for an error in Haskell?

  • 0

Based on SO question 13350164 How do I test for an error in Haskell?, I’m trying to write a unit test which asserts that given invalid input, a recursive function raises an exception. The approach I adopted works well for non-recursive functions (or when the first call raises the exception), but as soon as the exception occurs deeper in the call chain, the assertion fails.

I’ve read the excellent answers to question 6537766 Haskell approaches to error handling but unfortunately the advice is a bit too generic for this point of my learning curve. My guess is that the problem here is connected to lazy evaluation and non-pure testing code, but I’d appreciate an expert explanation.

Should I take a different approach to error handling in situations like this (e.g. Maybe or Either), or is there a reasonable fix for making the test case work correctly while using this style?

Here’s the code I’ve come up with. The first two test cases succeed, but the third one fails with "Received no exception, but was expecting exception: Negative item".

import Control.Exception (ErrorCall(ErrorCall), evaluate)
import Test.HUnit.Base  ((~?=), Test(TestCase, TestList))
import Test.HUnit.Text (runTestTT)
import Test.HUnit.Tools (assertRaises)

sumPositiveInts :: [Int] -> Int
sumPositiveInts [] = error "Empty list"
sumPositiveInts (x:[]) = x
sumPositiveInts (x:xs) | x >= 0 = x + sumPositiveInts xs
                       | otherwise = error "Negative item"

instance Eq ErrorCall where
    x == y = (show x) == (show y)

assertError msg ex f = 
    TestCase $ assertRaises msg (ErrorCall ex) $ evaluate f

tests = TestList [
  assertError "Empty" "Empty list" (sumPositiveInts ([]))
  , assertError "Negative head" "Negative item" (sumPositiveInts ([-1, -1]))
  , assertError "Negative second item" "Negative item" (sumPositiveInts ([1, -1]))
  ]   

main = runTestTT tests
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-18T15:09:57+00:00Added an answer on June 18, 2026 at 3:09 pm

    It’s actually just an error in sumPositiveInts. Your code does not do negativity checking when the only negative number is the last one in the list—the second branch doesn’t include the check.

    It’s worth noting that the canonical way of writing recursion like yours would break the “emptiness” test out in order to avoid this bug. Generally, decomposing your solution into “sum” plus two guards will help to avoid errors.


    I second the suggestion from Haskell approaches to error handling by the way. Control.Exception is much more difficult to reason about and learn and error should only be used to mark code branches which are impossible to achieve—I rather like some suggestions that it ought to have been called impossible.

    To make the suggestion tangible, we can rebuild this example using Maybe. First, the unguarded function is built in:

    sum :: Num a => [a] -> a
    

    then we need to build the two guards (1) empty lists give Nothing and (2) lists containing negative numbers give Nothing.

    emptyIsNothing :: [a] -> Maybe [a]
    emptyIsNothing [] = Nothing
    emptyIsNothing as = Just as
    
    negativeGivesNothing :: [a] -> Maybe [a]
    negativeGivesNothing xs | all (>= 0) xs = Just xs
                            | otherwise     = Nothing
    

    and we can combine them as a monad

    sumPositiveInts :: [a] -> Maybe a
    sumPositiveInts xs = do xs1 <- emptyIsNothing xs
                            xs2 <- negativeGivesNothing xs1
                            return (sum xs2)
    

    And then there are lots of idioms and reductions we can employ to make this code much easier to read and write (once you know the conventions!). Let me stress that nothing after this point is necessary nor terribly easy to understand. Learning it improves your ability to decompose functions and fluently think about FP, but I’m just jumping to the advanced stuff.

    For instance, we can use “Monadic (.)” (which is also called Kleisli arrow composition) to write sumPositiveInts

    sumPositiveInts :: [a] -> Maybe a
    sumPositiveInts = emptyIsNothing >=> negativeGivesNothing >=> (return . sum)
    

    and we can simplify both emptyIsNothing and negativeGivesNothing using a combinator

    elseNothing :: (a -> Bool) -> a -> Just a
    pred `elseNothing` x | pred x    = Just x
                         | otherwise = Nothing
    
    emptyIsNothing = elseNothing null
    
    negativeGivesNothing = sequence . map (elseNothing (>= 0))
    

    where sequence :: [Maybe a] -> Maybe [a] fails an entire list if any of the contained values are Nothing. We can actually go one step further since sequence . map f is a common idiom

    negativeGivesNothing = mapM (elseNothing (>= 0))
    

    So, in the end

    sumPositives :: [a] -> Maybe a
    sumPositives = elseNothing null 
                   >=> mapM (elseNothing (>= 0))
                   >=> return . sum
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I am working on a project which is basically a knowledge based question answering
This is a question based on: Trying to get tag-it to work with an
Based on this question I've created a small application which is catching all debug
This question is based on my previous question which I got a working answer
I just had a question based on MVC model, which I want to utilize
First I want to make it clear that this is a homework based question.
edit : I based this question on a false assumption - that the generic
I'm making an app that's based on question and answers, and the answers have
UPDATE (2010-12-21): Completely rewrote this question based on tests that I've been doing. Also,
I have edited this OS 3.2 question based on advice that it could infringe

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.