Why does QuickCheck insist on this class constraint?

Hello all, Ghc complainend about Could not deduce (Arbitrary a1) arising from a use of ‘arbitrary’ Could not deduce (Eq a1) arising from a use of ‘arbitrary’ in the following code .. data CList a = CList [Change a] deriving Show instance (Arbitrary c, Eq c) => Arbitrary (CList c) where arbitrary = do ts <- orderedList :: Gen[Time] vs <- listOf arbitrary :: Arbitrary c => Gen [c] return $ CList $ zipWith (\t v -> Chg t v) (nub ts) vs instance (Arbitrary a, Eq a) => Arbitrary (Temporal a) where arbitrary = do d <- arbitrary (CList cs) <- arbitrary :: (Arbitrary a, Eq a) => Gen (CList a) -- <=== return (Temporal d cs) ..if I leave out the class constraints in the line maked with "<===". Why is that so, i.e. why isn't the constraint four lines up (in the instance declaration) sufficient?

Why are you putting those type signatures everywhere ? Won't your code compile without them ? It seems to me that absent a strange Change type, all those things can be inferred... Are you doing this as an exercise or because you think it is more readable ? -- Jedaï

Am 04/01/2015 um 10:43 PM schrieb Chaddaï Fouché:
Why are you putting those type signatures everywhere ? Won't your code compile without them ? It seems to me that absent a strange Change type, all those things can be inferred... Are you doing this as an exercise or because you think it is more readable ?
I had put them there, because I thought QuickCheck needs them. But you're right they are not needed and then my question becomes a non-issue.

Hi. To answer your original question anyway: In Haskell 2010, all type variables that appear in any type annotation are implicitly quantified. They're not "scoped". So e.g. here: instance (Arbitrary a, Eq a) => Arbitrary (Temporal a) where arbitrary = do d <- arbitrary (CList cs) <- arbitrary :: (Arbitrary a, Eq a) => Gen (CList a) -- <=== return (Temporal d cs) if you say just "Gen (CList a)", it's the same as if you'd write "Gen (CList b)", and it means "forall b. Gen (CList b)". But that's not true! The term "arbitrary" cannot have the type "forall b. Gen (CList b)", because the instance for "Gen (CList c)" requires "(Arbitray c, Eq c)". That's why GHC wants you to add the constraint. However, you can make type variables scoped in GHC, by enabling the "ScopedTypeVariables" extension. So if you add the pragma {-# LANGUAGE ScopedTypeVariables #-} as the first line of your module, then the type variables that occur in the instance declaration scope over the body of the instance, and your annotations should mean what you originally expected and work without the extra constraints. But of course, as has already been stated, the type annotations are unnecessary here, because GHC can infer everything anyway. Cheers, Andres -- Andres Löh, Haskell Consultant Well-Typed LLP, http://www.well-typed.com Registered in England & Wales, OC335890 250 Ice Wharf, 17 New Wharf Road, London N1 9RF, England
participants (3)
-
Andres Löh
-
Chaddaï Fouché
-
martin