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?
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 Nothing
s and unwraps the items from the Just …
data constructor.