summaryrefslogtreecommitdiff
path: root/testsuite/tests/gadt/doaitse.hs
diff options
context:
space:
mode:
Diffstat (limited to 'testsuite/tests/gadt/doaitse.hs')
-rw-r--r--testsuite/tests/gadt/doaitse.hs55
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,())
+ )
+