{-# LANGUAGE GADTs, ExistentialQuantification, ScopedTypeVariables, RankNTypes #-} -- Here's an example from Doaitse Swiestra (Sept 06) -- which requires use of scoped type variables -- -- It's a cut-down version of a larger program -- -- It's also one which was sensitive to syntactic order -- in GHC 6.4; but not in 6.6 module ShouldCompile where data Exists f = forall a . Exists (f a) data Ref env a where Zero :: Ref (a,env') a Suc :: Ref env' a -> Ref (x,env') a data Find env final = Find (forall a . Ref env a -> Maybe (Ref final a)) data Equal a b where Eq :: Equal a a sym :: Equal a b -> Equal b a sym Eq = Eq match' :: Ref env' a -> Ref env'' a -> Bool match' _ _ = True match :: Ref env a -> Ref env b -> Maybe (Equal a b) match Zero Zero = Just Eq match (Suc x)(Suc y) = match x y match _ _ = Nothing -- Notice the essential type sig for the argument to Exists f1 :: forall env. (Exists (Ref env)) -> Exists (Find env) f1 (Exists (ref1 :: Ref env b)) = Exists ( Find (\ ref2 -> case match ref2 ref1 of Just Eq -> Just Zero _ -> Nothing ):: Find env (b,()) ) -- same as 'f1' except that 'ref1' and 'ref2' are swapped in the -- application of 'match' f2 :: forall env. (Exists (Ref env)) -> Exists (Find env) f2 (Exists (ref1 :: Ref env b)) = Exists (Find (\ ref2 -> case match ref1 ref2 of Just Eq -> Just Zero _ -> Nothing ) :: Find env (b,()) )