1

I have encountered a weird HUnit behavior. It does not allow to compile test cases if Nothing == Nothing condition is present in the test. Here is my code that reproduces this behavior:

module TestTest where 

import Control.Exception
import Control.Monad
import Test.HUnit
import Test.AssertError

testTests = test [ 
    "test A01"  ~: "x == x" ~: True ~=? Nothing == Nothing,
    "test _"    ~: "empty test" ~: True ~=? True
    ]

runTests :: IO Counts
runTests = do
    runTestTT testTests

Attempt to load the file with this contents in ghci returns following error:

[2 of 2] Compiling TestTest         ( Test/TestTest.hs, interpreted )

Test/TestTest.hs:9:49:
    No instance for (Eq a0) arising from a use of ‘==’
    The type variable ‘a0’ is ambiguous
    Note: there are several potential instances:
      instance Eq Counts -- Defined in ‘Test.HUnit.Base’
      instance Eq Node -- Defined in ‘Test.HUnit.Base’
      instance Eq State -- Defined in ‘Test.HUnit.Base’
      ...plus 53 others
    In the second argument of ‘(~=?)’, namely ‘Nothing == Nothing’
    In the second argument of ‘(~:)’, namely
      ‘True ~=? Nothing == Nothing’
    In the second argument of ‘(~:)’, namely
      ‘"x == x" ~: True ~=? Nothing == Nothing’
Failed, modules loaded: Test.AssertError.

Note that condition Just 2 == Just 2 in the same test case works fine. If I type Nothing == Nothing in ghci, it returns True as expected.

Any ideas why HUnit might behave this way? Is this a bug or expected behavior?

Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
altern
  • 5,829
  • 5
  • 44
  • 72

1 Answers1

3

The problem is that you specify two Nothings, and none of these thus hint what the type of a will be. Of course you can reason that for Nothing it does not matter. But Haskell does not reason that way: it is interested in "to what (==) function should I point?".

You can resolve the problem by making the type explicit. For instance:

testTests = test [ 
  "test A01"  ~: "x == x" ~: True ~=? (Nothing :: Maybe Int) == Nothing,
  "test _"    ~: "empty test" ~: True ~=? True
  ]
Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
  • Why does then running `Nothing == Nothing` in `ghci` return `True` without specifying the whole type explicitly? – altern Jul 22 '17 at 13:34
  • @altern: because `ghci` postpones type grounding. Simply because it cannot do that immediately. `ghc` will interpret all the files and then reason about these. – Willem Van Onsem Jul 22 '17 at 13:36
  • 7
    @altern Because of [extended defaulting](https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/ghci.html#extended-default-rules), which chooses monomorphic types in ambiguous type situations more often, and which is turned on by default in ghci and off by default elsewhere. – Daniel Wagner Jul 22 '17 at 16:35