I'd like to run the classical test for reversing a list. To this end, I have to specialize the list to a list of "Arbitrary" (sic!) types, e.g. [Int].
What works is
module ListCheck where
import Test.QuickCheck
myReverse :: [Int] -> [Int]
myReverse = reverse
reverse_of_reverse_is_original = property (\xs -> myReverse(myReverse xs) == xs)
or factoring out the invariant like
reverse_invariant :: [Int] -> Bool
reverse_invariant xs = reverse(reverse xs) == xs
reverse_of_reverse_is_original = property reverse_invariant
but I would rather want to not wrap the original function but use it directly. The usual Haskell trick of forcing a specialization through adding
... where types = xs :: [Int]
does not work here.
Is there a less verbose solution?
It is unfortunately the case that the
where types = xs :: [Int]
gets removed by the let expression simplification and canonicalization pass, which comes before type checking even.
This is, so to speak, a side effect of dependency analysis, where it is seen that types
is totally useless.
You can write:
p_rev = property rev
where rev (xs::[Int]) = (reverse . reverse) xs == xs
or even:
p_rev = forAll (arbitrary :: Gen [Int])
(\xs -> (reverse . reverse) xs == xs)
Since one could write nonsense like
where types = 1:true:"foo" + Just []
and it would still get removed, it would arguably be better to remove unused lets only after typechecking.