diff options
Diffstat (limited to 'testsuite/tests/gadt/doaitse.hs')
-rw-r--r-- | testsuite/tests/gadt/doaitse.hs | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/testsuite/tests/gadt/doaitse.hs b/testsuite/tests/gadt/doaitse.hs new file mode 100644 index 0000000000..51525bb573 --- /dev/null +++ b/testsuite/tests/gadt/doaitse.hs @@ -0,0 +1,55 @@ +{-# LANGUAGE GADTs, ExistentialQuantification, ScopedTypeVariables, + Rank2Types #-} + +-- 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,()) + ) + |