[Haskell-beginners] Why does QuickCheck insist on this class constraint?

Andres Löh andres at well-typed.com
Fri Apr 10 17:51:23 UTC 2015


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


More information about the Beginners mailing list