Вопрос

I am writing a test for a binary search function I wrote.

module Tests where

import Data.List (sort)
import Test.QuickCheck
import BinarySearch (binarySearch)

prop_equals_elem x xs = (binarySearch x $ sort xs) == (x `elem` xs)

args = Args {replay = Nothing, maxSuccess = 200, maxDiscard=200, maxSize=200, chatty = False}

main = do
    quickCheck (prop_equals_elem :: (Ord a) => a -> [a] -> Bool)

It works well using quickCheck in ghci but when I try to run main it gives the error

Tests.hs:12:5:
    Ambiguous type variable `a0' in the constraints:
      (Arbitrary a0) arising from a use of `quickCheckWith'
          at Tests.hs:12:5-18
      (Show a0) arising from a use of `quickCheckWith'
          at Tests.hs:12:5-18
      (Ord a0) arising from an expression type signature
          at Tests.hs:12:26-72

Why does this not work in main but does in ghci?

Это было полезно?

Решение

This is likely caused by the extended defaulting rules in GHCi.

When testing a function like this, you need to use a concrete element type. GHCi will default the element type to () because of the extended rules, but this will not happen when compiling the code normally, so GHC is telling you that it cannot figure out which element type to use.

You can for example use Int instead for the test. () is pretty useless for testing this function, as all elements would be the same.

quickCheck (prop_equals_elem :: Int -> [Int] -> Bool)

If it works for Int, it should work for any type due to parametricity.

Другие советы

When you run a QuickCheck test, QuickCheck needs to know how to generate data. Here, you've told it only that your code should work with an arbitrary type of the Ord type class, which isn't enough for it to start testing. Hence the error about ambiguous type classes.

If you just need an arbitrary Ord instance, as it appears here, then something like Int would be a good choice for your testing. It's a simple type with a linear order. So try fixing your type to Int in main, as in:

quickCheck (prop_equals_elem :: Int -> [Int] -> Bool)

As for why it works in GHCi, the answer is defaulting. GHCi defaults type variables to () whenever possible, just to avoid giving spurious errors in situations where you really don't care about a value. Actually that's an awful choice: you won't test anything interesting by only testing with the () type! So again, the explicit type signature is better.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top