summaryrefslogtreecommitdiff
path: root/testsuite/tests/typecheck/should_run/T3731.hs
diff options
context:
space:
mode:
Diffstat (limited to 'testsuite/tests/typecheck/should_run/T3731.hs')
-rw-r--r--testsuite/tests/typecheck/should_run/T3731.hs213
1 files changed, 213 insertions, 0 deletions
diff --git a/testsuite/tests/typecheck/should_run/T3731.hs b/testsuite/tests/typecheck/should_run/T3731.hs
new file mode 100644
index 0000000000..af858e570a
--- /dev/null
+++ b/testsuite/tests/typecheck/should_run/T3731.hs
@@ -0,0 +1,213 @@
+{-# LANGUAGE DeriveDataTypeable,
+ FlexibleContexts, FlexibleInstances,
+ MultiParamTypeClasses,
+ OverlappingInstances, UndecidableInstances,
+ Rank2Types, KindSignatures, EmptyDataDecls #-}
+
+{-# OPTIONS_GHC -Wall #-}
+
+module Main (main) where
+
+import Data.Typeable
+
+class Sat a where
+ dict :: a
+
+data Proxy (a :: * -> *)
+
+class ( Sat (ctx a)) => Data ctx a where
+ gunfold :: Proxy ctx
+ -> (forall b r. Data ctx b => c (b -> r) -> c r)
+ -> (forall r. r -> c r)
+ -> Constr
+ -> c a
+ dataTypeOf :: Proxy ctx -> a -> DataType
+
+newtype ID x = ID { unID :: x }
+
+fromConstrB :: Data ctx a
+ => Proxy ctx
+ -> (forall b. Data ctx b => b)
+ -> Constr
+ -> a
+fromConstrB ctx f = unID . gunfold ctx k z
+ where
+ k c = ID (unID c f)
+ z = ID
+
+data DataType = DataType
+ { tycon :: String
+ , datarep :: DataRep
+ }
+
+data Constr = Constr { conrep :: ConstrRep
+ , constring :: String
+ , confields :: [String]
+ , confixity :: Fixity
+ , datatype :: DataType
+ }
+
+data DataRep = AlgRep [Constr]
+data ConstrRep = AlgConstr ConIndex
+
+type ConIndex = Int
+
+data Fixity = Prefix
+ | Infix
+
+constrRep :: Constr -> ConstrRep
+constrRep = conrep
+
+-- | Constructs an algebraic datatype
+mkDataType :: String -> [Constr] -> DataType
+mkDataType str cs = DataType
+ { tycon = str
+ , datarep = AlgRep cs
+ }
+
+
+-- | Constructs a constructor
+mkConstr :: DataType -> String -> [String] -> Fixity -> Constr
+mkConstr dt str fields fix =
+ Constr
+ { conrep = AlgConstr idx
+ , constring = str
+ , confields = fields
+ , confixity = fix
+ , datatype = dt
+ }
+ where
+ idx = head [ i | (c,i) <- dataTypeConstrs dt `zip` [1..],
+ showConstr c == str ]
+
+
+-- | Gets the constructors
+dataTypeConstrs :: DataType -> [Constr]
+dataTypeConstrs dt = case datarep dt of
+ AlgRep cons -> cons
+
+-- | Gets the string for a constructor
+showConstr :: Constr -> String
+showConstr = constring
+
+-- | Gets the index of a constructor
+constrIndex :: Constr -> ConIndex
+constrIndex con = case constrRep con of
+ AlgConstr idx -> idx
+
+nilConstr :: Constr
+nilConstr = mkConstr listDataType "[]" [] Prefix
+consConstr :: Constr
+consConstr = mkConstr listDataType "(:)" [] Infix
+listDataType :: DataType
+listDataType = mkDataType "Prelude.[]" [nilConstr,consConstr]
+
+instance (Sat (ctx [a]), Data ctx a) =>
+ Data ctx [a] where
+ gunfold _ k z c = case constrIndex c of
+ 1 -> z []
+ 2 -> k (k (z (:)))
+ _ -> error "gunfold List"
+ dataTypeOf _ _ = listDataType
+
+class (Data DefaultD a) => Default a where
+ defaultValue :: a
+ defaultValue = defaultDefaultValue
+
+defaultDefaultValue :: Data DefaultD a => a
+{-# NOINLINE defaultDefaultValue #-}
+defaultDefaultValue = res
+ where res = case datarep $ dataTypeOf defaultProxy res of
+ AlgRep (c:_) ->
+ fromConstrB defaultProxy (defaultValueD dict) c
+ AlgRep [] ->
+ error "defaultDefaultValue: Bad DataRep"
+
+data DefaultD a = DefaultD { defaultValueD :: a }
+
+defaultProxy :: Proxy DefaultD
+defaultProxy = error "defaultProxy"
+
+-- dfun3
+instance Default t => Sat (DefaultD t) where
+ dict = DefaultD { defaultValueD = defaultValue }
+
+-- dfun5
+instance Default a => Default [a] where
+ defaultValue = []
+data Proposition = Proposition Expression deriving (Show, Typeable)
+data Expression = Conjunction [Expression] deriving (Show, Typeable)
+
+constr_Proposition :: Constr
+constr_Proposition = mkConstr dataType_Proposition "Proposition" [] Prefix
+dataType_Proposition :: DataType
+dataType_Proposition = mkDataType "Proposition" [constr_Proposition]
+
+-- dfun1
+instance Data DefaultD Proposition
+ where gunfold _ k z c = case constrIndex c of
+ 1 -> k (z Proposition)
+ _ -> error "gunfold: fallthrough"
+ dataTypeOf _ _ = dataType_Proposition
+
+constr_Conjunction :: Constr
+constr_Conjunction = mkConstr dataType_Expression "Conjunction" [] Prefix
+dataType_Expression :: DataType
+dataType_Expression = mkDataType "Expression" [constr_Conjunction]
+
+-- dfun2
+instance (Sat (ctx [Expression]), Sat (ctx Expression))
+ => Data ctx Expression
+ where gunfold _ k z c = case constrIndex c of
+ 1 -> k (z Conjunction)
+ _ -> error "gunfold: fallthrough"
+ dataTypeOf _ _ = dataType_Expression
+
+-- dfun0
+instance Default Proposition where
+ defaultValue = defaultDefaultValue
+
+-- dfun4
+instance Default Expression where
+ defaultValue = defaultDefaultValue
+
+main :: IO ()
+main = putStrLn (show (defaultValue :: Proposition))
+
+{- The trouble comes from "instance Default Expression"
+
+Define: dfun4 : Default Expression = MkDefault d_aCl (..)
+
+Simplify the superclass:
+ Wanted: d_aCl : Data DefaultD Expression
+ Derived: d_aCn : Sat DefaultD Expression d_aCn = $p1 d_aCl {irrelevant}
+
+ by dfun2 d_aCl = dfun2 d_aCo d_aCp
+ Wanted: d_aCo : Sat (DefaultD [Expression])
+ d_aCp : Sat (DefaultD Expression)
+
+ by dfun3 d_aCo = dfun3 d_aCq
+ Wanted: d_aCq : Default [Expression]
+ Derived: d_aCr : Data DefaultD [Expression] d_aCr = $p1 d_aCq {irrelevant}
+
+ by dfun5 d_aCq = dfun5 aCu
+ Wanted: d_aCu : Default Expression
+ Derived: d_aCw : Data DefaultD Expression d_aCw = $p1 d_aCu
+ Derived: d_aCx : Sat (DefaultD Expression) d_aCx = $p1 d_aCw
+ -- These two deriveds are unnecessary,
+ -- and dangerous, because we later satisfy
+ -- d_aCu from dfun4 which does not visibly
+ -- depend on d_aCl
+
+Now we satisfy d_aCu = dfun4
+ d_aCp = d_aCx
+Result = disaster:
+ d_aCp = d_aCx
+ = $p1 d_aCw
+ = $p1 ($p1 d_aCu)
+ = $p1 ($p1 dfun4)
+ = $p1 ($p1 (MkDefault d_aCl ...))
+ = $p1 d_aCl
+ = $p1 (dfun2 d_aCo d_aCp)
+ = d_aCp
+-}