Why does QuickCheck insist on this class constraint?

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

Why does QuickCheck insist on this class constraint?

Martin Drautzburg
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?

Reply | Threaded
Open this post in threaded view
|

Why does QuickCheck insist on this class constraint?

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 ?

--
Jeda?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/beginners/attachments/20150401/69dcd987/attachment.html>

Reply | Threaded
Open this post in threaded view
|

Why does QuickCheck insist on this class constraint?

Martin Drautzburg
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.

Reply | Threaded
Open this post in threaded view
|

Why does QuickCheck insist on this class constraint?

Andres Löh
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