I have written a function in Haskell that takes a list of arbitrary elements and returns (mapped) a list of tuples. Each tuple contains the original element and a fraction, with all the fractions in the list adding to 1 (therefore I simply calculate the fraction once using 1 ``div`` length xs
and apply it all elements). This is the code:
uniform :: [a] -> [(a, Int)]
uniform xs = map (\x -> (x, prob)) xs
where prob = 1 `div` (length xs)
(Disclaimer: This is actually a slightly simplified version, but I am producing the exact same behaviour, so hopefully this suffices).
I am trying to cover this with a property based test using Hspec and Quickcheck:
spec = do
describe "uniform" $ do
it "produces a uniform distribution summing to 1" $ property $
let totalProbability ((_, p):xs) = p + (totalProbability xs)
in (\xs -> (totalProbability $ uniform xs) `shouldBe` 1)
However when I run this I get this error:
• Ambiguous type variable ‘a0’ arising from a use of ‘property’
prevents the constraint ‘(Arbitrary a0)’ from being solved.
Probable fix: use a type annotation to specify what ‘a0’ should be.
These potential instances exist:
instance (Arbitrary a, Arbitrary b) => Arbitrary (Either a b)
-- Defined in ‘Test.QuickCheck.Arbitrary’
instance Arbitrary Ordering
-- Defined in ‘Test.QuickCheck.Arbitrary’
instance Arbitrary Integer
-- Defined in ‘Test.QuickCheck.Arbitrary’
...plus 19 others
...plus 62 instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
• In the second argument of ‘($)’, namely
‘property
$ let totalProbability ((_, p) : xs) = p + (totalProbability xs)
in (\ xs -> (totalProbability $ uniform xs) `shouldBe` 1)’
In a stmt of a 'do' block:
it "produces a uniform distribution summing to 1"
$ property
$ let totalProbability ((_, p) : xs) = p + (totalProbability xs)
in (\ xs -> (totalProbability $ uniform xs) `shouldBe` 1)
In the second argument of ‘($)’, namely
‘do it "produces a uniform distribution summing to 1"
$ property
$ let totalProbability ((_, p) : xs) = ...
in (\ xs -> (totalProbability $ uniform xs) `shouldBe` 1)’
| 12 | it "produces a uniform distribution summing to 1" $ property $ | ^^^^^^^^^^...
I am guessing that somewhere I have not given QuickCheck enough information about how to generate the test value, but I am not sure where to go from here.
Any help would be greatly appreciated.
Thanks!
You need to specify a type for xs
: is that a list of strings? ints? booleans? This is so that QuickCheck can generate a random sample in that type.
You can write, for instance:
...
in (\xs -> (totalProbability $ uniform (xs :: [Int])) `shouldBe` 1)