Cases involving empty lists does not compile when using Filter to remove Nothing cases

For an assignment I have to write a function that uses filter on a list of Maybe instances, removing all with a value of Nothing. We’re supposed to make sure the function works using Hspec.

It’s simple to get it working with a case containing elements before and after running using Data.Maybe (isJust):

onlyJust :: [Maybe a] -> [Maybe a]
onlyJust = filter isJust

But, as soon as I try to apply the function to a test case such as

it "produces the list []" $
    onlyJust [Nothing, Nothing] `shouldBe` []

or

it "produces the list []" $
    onlyJust [] `shouldBe` []

the test suite file does not compile, giving an ambiguous type error.

• Ambiguous type variable ‘a0’ arising from a use of ‘shouldBe’
  prevents the constraint ‘(Show a0)’ from being solved.
  Probable fix: use a type annotation to specify what ‘a0’ should be.

I’ve attempted to add a type annotation as the error message suggests, but I cannot find one that matches the type constraints on the function itself. For the latter test case, I’ve also tried modifying the function by adding an empty case:

onlyJust :: [Maybe a] -> [Maybe a]
onlyJust [] = []
onlyJust l = filter isJust l

but the error still persists. Am I glossing over an obvious type annotation to fix this issue, or is there a flaw in how the function is written that means it can’t handle outputting an empty list or taking one in as input?

>Solution :

For onlyJust [Nothing, Nothing] shouldBe [] it does not know what value to pick for the a in Maybe a, hence the error. You can add a type hint, like:

onlyJust ([Nothing, Nothing] :: [Maybe Int]) `shouldBe` []

the same for the empty list:

onlyJust ([] :: [Maybe Int]) `shouldBe` []

Note that there is already a catMaybes :: [Maybe a] -> [a] which filters out the Nothings and unwraps the items from the Just … data constructor.

Leave a Reply