Search code examples
testinghaskellhunit

How to work with assertEqual with parameterized types


I'm trying to do the exercises in Real World Haskell in a TDD fashion, using HUnit. As you probably guessed I haven't gotten far yet so I'm an absolute beginner when it comes to Haskell. Given the following code how can I resolve the following error ghci produces:

Ambiguous type variable a' in the constraints: Show a' arising from a use of assertEqual' at List_Test.hs:6:27-58 Eq a' arising from a use of `assertEqual' at List_Test.hs:6:27-58 Probable fix: add a type signature that fixes these type variable(s)

List_Test.hs:

module List_Test
where
import List
import Test.HUnit

fromEmptyList = TestCase $ assertEqual "" [] (toList (Nil))

main = runTestTT fromEmptyList

List.hs:

module List
where
data List a = Cons a (List a)
            | Nil
              deriving (Show)

toList Nil = []
toList (Cons a b) = (:) a (toList b) 

I've tried adding type constraints to both the List declaration and the toList definition without success. A internet search did also not provide any information.


Solution

  • The issue is partially that GHC does not know that toList Nil will return an empty list.

    *List> :i toList
    toList :: List a -> [a]     -- Defined at List.hs:7:0-5
    

    It only knows that it will return a list of type a, but it has no idea what a is -- hence the "ambiguous type variable a" message. One way to work around this is to just specify the type of list that toList will return:

    fromEmptyList = TestCase $ assertEqual "" [] (toList (Nil) :: [Int])
    

    Changing that, and removing the first two lines of List_Test (it will not look for a main function in a named module that is not named Main), gave me this result:

    $ runghc List_Test.hs 
    Cases: 1  Tried: 1  Errors: 0  Failures: 0