singletons 0.9.3 → 0.10.0
raw patch · 94 files changed
+14421/−3182 lines, 94 filesdep +Cabaldep +constraintsdep +filepathdep −sybdep ~base
Dependencies added: Cabal, constraints, filepath, process, tasty, tasty-golden
Dependencies removed: syb
Dependency ranges changed: base
Files
- CHANGES.md +17/−0
- Data/Singletons.hs +0/−127
- Data/Singletons/Bool.hs +0/−111
- Data/Singletons/Core.hs +0/−144
- Data/Singletons/CustomStar.hs +0/−182
- Data/Singletons/Decide.hs +0/−30
- Data/Singletons/Either.hs +0/−107
- Data/Singletons/Eq.hs +0/−75
- Data/Singletons/List.hs +0/−70
- Data/Singletons/Maybe.hs +0/−120
- Data/Singletons/Prelude.hs +0/−102
- Data/Singletons/Promote.hs +0/−689
- Data/Singletons/Singletons.hs +0/−740
- Data/Singletons/TH.hs +0/−89
- Data/Singletons/Tuple.hs +0/−61
- Data/Singletons/TypeRepStar.hs +0/−98
- Data/Singletons/Types.hs +0/−55
- Data/Singletons/Util.hs +0/−274
- Data/Singletons/Void.hs +0/−78
- README.md +38/−3
- singletons.cabal +43/−27
- src/Data/Singletons.hs +182/−0
- src/Data/Singletons/Bool.hs +102/−0
- src/Data/Singletons/CustomStar.hs +181/−0
- src/Data/Singletons/Decide.hs +55/−0
- src/Data/Singletons/Either.hs +107/−0
- src/Data/Singletons/Eq.hs +51/−0
- src/Data/Singletons/Instances.hs +29/−0
- src/Data/Singletons/List.hs +69/−0
- src/Data/Singletons/Maybe.hs +121/−0
- src/Data/Singletons/Prelude.hs +106/−0
- src/Data/Singletons/Promote.hs +699/−0
- src/Data/Singletons/Singletons.hs +738/−0
- src/Data/Singletons/TH.hs +86/−0
- src/Data/Singletons/Tuple.hs +61/−0
- src/Data/Singletons/TypeLits.hs +181/−0
- src/Data/Singletons/TypeRepStar.hs +99/−0
- src/Data/Singletons/Types.hs +64/−0
- src/Data/Singletons/Util.hs +267/−0
- src/Data/Singletons/Void.hs +78/−0
- tests/SingletonsTestSuite.hs +41/−0
- tests/SingletonsTestSuiteUtils.hs +233/−0
- tests/compile-and-dump/GradingClient/Database.ghc76.template +4470/−0
- tests/compile-and-dump/GradingClient/Database.ghc78.template +3812/−0
- tests/compile-and-dump/GradingClient/Database.hs +536/−0
- tests/compile-and-dump/GradingClient/Main.ghc76.template +75/−0
- tests/compile-and-dump/GradingClient/Main.ghc78.template +75/−0
- tests/compile-and-dump/GradingClient/Main.hs +53/−0
- tests/compile-and-dump/InsertionSort/InsertionSortImp.ghc76.template +77/−0
- tests/compile-and-dump/InsertionSort/InsertionSortImp.ghc78.template +75/−0
- tests/compile-and-dump/InsertionSort/InsertionSortImp.hs +206/−0
- tests/compile-and-dump/Promote/NumArgs.ghc76.template +10/−0
- tests/compile-and-dump/Promote/NumArgs.ghc78.template +10/−0
- tests/compile-and-dump/Promote/NumArgs.hs +12/−0
- tests/compile-and-dump/Promote/PatternMatching.ghc76.template +65/−0
- tests/compile-and-dump/Promote/PatternMatching.ghc78.template +65/−0
- tests/compile-and-dump/Promote/PatternMatching.hs +20/−0
- tests/compile-and-dump/Singletons/AtPattern.ghc76.template +16/−0
- tests/compile-and-dump/Singletons/AtPattern.ghc78.template +16/−0
- tests/compile-and-dump/Singletons/AtPattern.hs +11/−0
- tests/compile-and-dump/Singletons/BadPlus.ghc76.template +2/−0
- tests/compile-and-dump/Singletons/BadPlus.ghc78.template +2/−0
- tests/compile-and-dump/Singletons/BadPlus.hs +11/−0
- tests/compile-and-dump/Singletons/BoxUnBox.ghc76.template +28/−0
- tests/compile-and-dump/Singletons/BoxUnBox.ghc78.template +27/−0
- tests/compile-and-dump/Singletons/BoxUnBox.hs +9/−0
- tests/compile-and-dump/Singletons/Contains.ghc76.template +19/−0
- tests/compile-and-dump/Singletons/Contains.ghc78.template +18/−0
- tests/compile-and-dump/Singletons/Contains.hs +13/−0
- tests/compile-and-dump/Singletons/DataValues.ghc76.template +46/−0
- tests/compile-and-dump/Singletons/DataValues.ghc78.template +45/−0
- tests/compile-and-dump/Singletons/DataValues.hs +18/−0
- tests/compile-and-dump/Singletons/Empty.ghc76.template +15/−0
- tests/compile-and-dump/Singletons/Empty.ghc78.template +15/−0
- tests/compile-and-dump/Singletons/Empty.hs +7/−0
- tests/compile-and-dump/Singletons/EqInstances.ghc76.template +17/−0
- tests/compile-and-dump/Singletons/EqInstances.ghc78.template +22/−0
- tests/compile-and-dump/Singletons/EqInstances.hs +8/−0
- tests/compile-and-dump/Singletons/HigherOrder.ghc76.template +33/−0
- tests/compile-and-dump/Singletons/HigherOrder.ghc78.template +33/−0
- tests/compile-and-dump/Singletons/HigherOrder.hs +15/−0
- tests/compile-and-dump/Singletons/Maybe.ghc76.template +53/−0
- tests/compile-and-dump/Singletons/Maybe.ghc78.template +54/−0
- tests/compile-and-dump/Singletons/Maybe.hs +7/−0
- tests/compile-and-dump/Singletons/Nat.ghc76.template +79/−0
- tests/compile-and-dump/Singletons/Nat.ghc78.template +80/−0
- tests/compile-and-dump/Singletons/Nat.hs +18/−0
- tests/compile-and-dump/Singletons/Operators.ghc76.template +56/−0
- tests/compile-and-dump/Singletons/Operators.ghc78.template +56/−0
- tests/compile-and-dump/Singletons/Operators.hs +18/−0
- tests/compile-and-dump/Singletons/Star.ghc76.template +188/−0
- tests/compile-and-dump/Singletons/Star.ghc78.template +142/−0
- tests/compile-and-dump/Singletons/Star.hs +14/−0
- tests/compile-and-dump/buildGoldenFiles.awk +1/−0
CHANGES.md view
@@ -1,6 +1,23 @@ Changelog for singletons project ================================ +0.10.0+------++Template Haskell names are now more hygienic. In other words, `singletons`+won't try to gobble up something happened to be named `Sing` in your project.+(Note that the Template Haskell names are not *completely* hygienic; names+generated during singleton generation can still cause conflicts.)++If a function to be promoted or singletonized is missing a type signature,+that is now an *error*, not a warning.++Added a new external module Data.Singletons.TypeLits, which contain the+singletons for GHC.TypeLits. Some convenience functions are also provided.++The extension `EmptyCase` is no longer needed. This caused pain when trying+to support both GHC 7.6.3 and 7.8.+ 0.9.3 -----
− Data/Singletons.hs
@@ -1,127 +0,0 @@-{-# LANGUAGE MagicHash, RankNTypes, PolyKinds, GADTs, DataKinds,- FlexibleContexts, CPP, TypeFamilies #-}---------------------------------------------------------------------------------- |--- Module : Data.Singletons--- Copyright : (C) 2013 Richard Eisenberg--- License : BSD-style (see LICENSE)--- Maintainer : Richard Eisenberg (eir@cis.upenn.edu)--- Stability : experimental--- Portability : non-portable------ This module exports the basic definitions to use singletons. For routine--- use, consider importing 'Data.Singletons.Prelude', which exports constructors--- for singletons based on types in the @Prelude@.------ You may also want to read--- <http://www.cis.upenn.edu/~eir/packages/singletons/README.html> and the--- original paper presenting this library, available at--- <http://www.cis.upenn.edu/~eir/papers/2012/singletons/paper.pdf>.----------------------------------------------------------------------------------module Data.Singletons (- -- * Main singleton definitions- - Sing,- -- | See also 'Data.Singletons.Prelude.Sing' for exported constructors- - SingI(..), SingKind(..),-- -- * Working with singletons- KindOf, Demote,- SingInstance(..), SomeSing(..),- singInstance, withSingI, withSomeSing, singByProxy,--#if __GLASGOW_HASKELL__ >= 707- singByProxy#,-#endif- withSing, singThat,-- -- * Auxiliary functions- bugInGHC, Error, sError,- KProxy(..), Proxy(..)- ) where--import Data.Singletons.Core-import Unsafe.Coerce-import GHC.TypeLits (Symbol)--#if __GLASGOW_HASKELL__ >= 707-import GHC.Exts ( Proxy# )-import Data.Proxy-#else-import Data.Singletons.Types-#endif---- | A 'SingInstance' wraps up a 'SingI' instance for explicit handling.-data SingInstance (a :: k) where- SingInstance :: SingI a => SingInstance a---- dirty implementation of explicit-to-implicit conversion-newtype DI a = Don'tInstantiate (SingI a => SingInstance a)---- | Get an implicit singleton (a 'SingI' instance) from an explicit one.-singInstance :: forall (a :: k). Sing a -> SingInstance a-singInstance s = with_sing_i SingInstance- where- with_sing_i :: (SingI a => SingInstance a) -> SingInstance a- with_sing_i si = unsafeCoerce (Don'tInstantiate si) s---- | Convenience function for creating a context with an implicit singleton--- available.-withSingI :: Sing n -> (SingI n => r) -> r-withSingI sn r =- case singInstance sn of- SingInstance -> r---- | Convert a normal datatype (like 'Bool') to a singleton for that datatype,--- passing it into a continuation.-withSomeSing :: SingKind ('KProxy :: KProxy k)- => DemoteRep ('KProxy :: KProxy k) -- ^ The original datatype- -> (forall (a :: k). Sing a -> r) -- ^ Function expecting a singleton- -> r-withSomeSing x f =- case toSing x of- SomeSing x' -> f x'---- | A convenience function useful when we need to name a singleton value--- multiple times. Without this function, each use of 'sing' could potentially--- refer to a different singleton, and one has to use type signatures (often--- with @ScopedTypeVariables@) to ensure that they are the same.-withSing :: SingI a => (Sing a -> b) -> b-withSing f = f sing---- | A convenience function that names a singleton satisfying a certain--- property. If the singleton does not satisfy the property, then the function--- returns 'Nothing'. The property is expressed in terms of the underlying--- representation of the singleton.-singThat :: forall (a :: k). (SingKind ('KProxy :: KProxy k), SingI a)- => (Demote a -> Bool) -> Maybe (Sing a)-singThat p = withSing $ \x -> if p (fromSing x) then Just x else Nothing---- | Allows creation of a singleton when a proxy is at hand.-singByProxy :: SingI a => proxy a -> Sing a-singByProxy _ = sing--#if __GLASGOW_HASKELL__ >= 707--- | Allows creation of a singleton when a @proxy#@ is at hand.-singByProxy# :: SingI a => Proxy# a -> Sing a-singByProxy# _ = sing-#endif---- | GHC 7.8 sometimes warns about incomplete pattern matches when no such--- patterns are possible, due to GADT constraints.--- See the bug report at <https://ghc.haskell.org/trac/ghc/ticket/3927>.--- In such cases, it's useful to have a catch-all pattern that then has--- 'bugInGHC' as its right-hand side.-bugInGHC :: forall a. a-bugInGHC = error "Bug encountered in GHC -- this should never happen"---- | The promotion of 'error'-type family Error (str :: Symbol) :: k---- | The singleton for 'error'-sError :: Sing (str :: Symbol) -> a-sError sstr = error (fromSing sstr)
− Data/Singletons/Bool.hs
@@ -1,111 +0,0 @@-{-# LANGUAGE TemplateHaskell, DataKinds, PolyKinds, TypeFamilies, TypeOperators,- GADTs, CPP #-}--#if __GLASGOW_HASKELL__ < 707-{-# OPTIONS_GHC -fno-warn-name-shadowing #-}-#endif---------------------------------------------------------------------------------- |--- Module : Data.Singletons.Bool--- Copyright : (C) 2013 Richard Eisenberg--- License : BSD-style (see LICENSE)--- Maintainer : Richard Eisenberg (eir@cis.upenn.edu)--- Stability : experimental--- Portability : non-portable------ Defines functions and datatypes relating to the singleton for 'Bool',--- including a singletons version of all the definitions in @Data.Bool@.------ Because many of these definitions are produced by Template Haskell,--- it is not possible to create proper Haddock documentation. Please look--- up the corresponding operation in @Data.Bool@. Also, please excuse--- the apparent repeated variable names. This is due to an interaction--- between Template Haskell and Haddock.----------------------------------------------------------------------------------module Data.Singletons.Bool (- -- * The 'Bool' singleton- - Sing(SFalse, STrue),- -- | Though Haddock doesn't show it, the 'Sing' instance above declares- -- constructors- --- -- > SFalse :: Sing False- -- > STrue :: Sing True- - SBool,- -- | 'SBool' is a kind-restricted synonym for 'Sing': @type SBool (a :: Bool) = Sing a@- - -- * Conditionals- If, sIf,-- -- * Singletons from @Data.Bool@- Not, sNot, (:&&), (:||), (%:&&), (%:||),-- -- | The following are derived from the function 'bool' in @Data.Bool@. The extra- -- underscore is to avoid name clashes with the type 'Bool'.- Bool_, sBool_, Otherwise, sOtherwise- ) where--import Data.Singletons.Core-import Data.Singletons.Singletons--#if __GLASGOW_HASKELL__ >= 707-import Data.Type.Bool--type a :&& b = a && b-type a :|| b = a || b--sNot :: SBool a -> SBool (Not a)-sNot SFalse = STrue-sNot STrue = SFalse--(%:&&) :: SBool a -> SBool b -> SBool (a :&& b)-SFalse %:&& _ = SFalse-STrue %:&& a = a--(%:||) :: SBool a -> SBool b -> SBool (a :|| b)-SFalse %:|| a = a-STrue %:|| _ = STrue--#else--$(singletonsOnly [d|- not :: Bool -> Bool- not False = True- not True = False-- (&&) :: Bool -> Bool -> Bool- False && _ = False- True && x = x-- (||) :: Bool -> Bool -> Bool- False || x = x- True || _ = True- |])---- | Type-level "If". @If True a b@ ==> @a@; @If False a b@ ==> @b@-type family If (a :: Bool) (b :: k) (c :: k) :: k-type instance If 'True b c = b-type instance If 'False b c = c--#endif---- | Conditional over singletons-sIf :: Sing a -> Sing b -> Sing c -> Sing (If a b c)-sIf STrue b _ = b-sIf SFalse _ c = c----- ... with some functions over Booleans-$(singletonsOnly [d|- bool_ :: a -> a -> Bool -> a- bool_ fls _tru False = fls- bool_ _fls tru True = tru-- otherwise :: Bool- otherwise = True- |])-
− Data/Singletons/Core.hs
@@ -1,144 +0,0 @@-{- Data/Singletons/Core.hs--(c) Richard Eisenberg 2013-eir@cis.upenn.edu--This (internal) module contains the main class definitions for singletons,-re-exported from various places.---}--{-# LANGUAGE CPP, RankNTypes, DataKinds, PolyKinds, GADTs, TypeFamilies,- FlexibleContexts, TemplateHaskell, ScopedTypeVariables,- UndecidableInstances, TypeOperators, FlexibleInstances #-}-#if __GLASGOW_HASKELL__ >= 707-{-# LANGUAGE EmptyCase #-}-#else- -- optimizing instances of SDecide cause GHC to die (#8467)-{-# OPTIONS_GHC -O0 #-}-#endif--module Data.Singletons.Core where--import Data.Singletons.Util-import Data.Singletons.Singletons-import GHC.TypeLits (Nat, Symbol)-import Data.Singletons.Types-import Unsafe.Coerce--#if __GLASGOW_HASKELL__ >= 707-import GHC.TypeLits (KnownNat, KnownSymbol, natVal, symbolVal)-import Data.Proxy-import Data.Type.Equality-#else-import qualified GHC.TypeLits as TypeLits-#endif---- | Convenient synonym to refer to the kind of a type variable:--- @type KindOf (a :: k) = ('KProxy :: KProxy k)@-type KindOf (a :: k) = ('KProxy :: KProxy k)---- | The singleton kind-indexed data family.-data family Sing (a :: k)---- | A 'SingI' constraint is essentially an implicitly-passed singleton.--- If you need to satisfy this constraint with an explicit singleton, please--- see 'withSingI'.-class SingI (a :: k) where- -- | Produce the singleton explicitly. You will likely need the @ScopedTypeVariables@- -- extension to use this method the way you want.- sing :: Sing a---- | The 'SingKind' class is essentially a /kind/ class. It classifies all kinds--- for which singletons are defined. The class supports converting between a singleton--- type and the base (unrefined) type which it is built from.-class (kparam ~ 'KProxy) => SingKind (kparam :: KProxy k) where- -- | Get a base type from a proxy for the promoted kind. For example,- -- @DemoteRep ('KProxy :: KProxy Bool)@ will be the type @Bool@.- type DemoteRep kparam :: *-- -- | Convert a singleton to its unrefined version.- fromSing :: Sing (a :: k) -> DemoteRep kparam-- -- | Convert an unrefined type to an existentially-quantified singleton type.- toSing :: DemoteRep kparam -> SomeSing kparam---- | Convenient abbreviation for 'DemoteRep':--- @type Demote (a :: k) = DemoteRep ('KProxy :: KProxy k)@-type Demote (a :: k) = DemoteRep ('KProxy :: KProxy k)---- | An /existentially-quantified/ singleton. This type is useful when you want a--- singleton type, but there is no way of knowing, at compile-time, what the type--- index will be. To make use of this type, you will generally have to use a--- pattern-match:------ > foo :: Bool -> ...--- > foo b = case toSing b of--- > SomeSing sb -> {- fancy dependently-typed code with sb -}------ An example like the one above may be easier to write using 'withSomeSing'.-data SomeSing (kproxy :: KProxy k) where- SomeSing :: Sing (a :: k) -> SomeSing ('KProxy :: KProxy k)- --- some useful singletons-$(genSingletons basicTypes)---- define singletons for TypeLits--newtype instance Sing (n :: Nat) = SNat Integer-#if __GLASGOW_HASKELL__ >= 707-instance KnownNat n => SingI n where- sing = SNat (natVal (Proxy :: Proxy n))-#else-instance TypeLits.SingRep n Integer => SingI (n :: Nat) where- sing = SNat (TypeLits.fromSing (TypeLits.sing :: TypeLits.Sing n))-#endif-instance SingKind ('KProxy :: KProxy Nat) where- type DemoteRep ('KProxy :: KProxy Nat) = Integer- fromSing (SNat n) = n- toSing n = SomeSing (SNat n)--newtype instance Sing (n :: Symbol) = SSym String-#if __GLASGOW_HASKELL__ >= 707-instance KnownSymbol n => SingI n where- sing = SSym (symbolVal (Proxy :: Proxy n))-#else-instance TypeLits.SingRep n String => SingI (n :: Symbol) where- sing = SSym (TypeLits.fromSing (TypeLits.sing :: TypeLits.Sing n))-#endif-instance SingKind ('KProxy :: KProxy Symbol) where- type DemoteRep ('KProxy :: KProxy Symbol) = String- fromSing (SSym n) = n- toSing s = SomeSing (SSym s)- --- we need to decare SDecide and its instances here to avoid making--- the TestEquality instance an orphan---- | Members of the 'SDecide' "kind" class support decidable equality. Instances--- of this class are generated alongside singleton definitions for datatypes that--- derive an 'Eq' instance.-class (kparam ~ 'KProxy) => SDecide (kparam :: KProxy k) where- -- | Compute a proof or disproof of equality, given two singletons.- (%~) :: forall (a :: k) (b :: k). Sing a -> Sing b -> Decision (a :~: b)--$(singDecideInstances basicTypes)---- We need SDecide instances for the TypeLits singletons-instance SDecide ('KProxy :: KProxy Nat) where- (SNat n) %~ (SNat m)- | n == m = Proved $ unsafeCoerce Refl- | otherwise = Disproved (\_ -> error errStr)- where errStr = "Broken Nat singletons"- -instance SDecide ('KProxy :: KProxy Symbol) where- (SSym n) %~ (SSym m)- | n == m = Proved $ unsafeCoerce Refl- | otherwise = Disproved (\_ -> error errStr)- where errStr = "Broken Symbol singletons"--instance SDecide ('KProxy :: KProxy k) => TestEquality (Sing :: k -> *) where- testEquality a b =- case a %~ b of- Proved Refl -> Just Refl- Disproved _ -> Nothing-
− Data/Singletons/CustomStar.hs
@@ -1,182 +0,0 @@-{-# LANGUAGE DataKinds, TypeFamilies, KindSignatures, CPP, TemplateHaskell #-}---------------------------------------------------------------------------------- |--- Module : Data.Singletons.CustomStar--- Copyright : (C) 2013 Richard Eisenberg--- License : BSD-style (see LICENSE)--- Maintainer : Richard Eisenberg (eir@cis.upenn.edu)--- Stability : experimental--- Portability : non-portable------ This file implements 'singletonStar', which generates a datatype @Rep@ and associated--- singleton from a list of types. The promoted version of @Rep@ is kind @*@ and the--- Haskell types themselves. This is still very experimental, so expect unusual--- results!----------------------------------------------------------------------------------module Data.Singletons.CustomStar ( singletonStar ) where--import Language.Haskell.TH-import Language.Haskell.TH.Syntax ( Quasi(..) )-import Data.Singletons.Util-import Data.Singletons.Promote-import Data.Singletons.Singletons-import Control.Monad--#if __GLASGOW_HASKELL__ >= 707-import Data.Singletons.Core-import Data.Singletons.Types-import Data.Singletons.Eq-import Unsafe.Coerce-import Data.Type.Equality-#endif--{--The SEq instance here is tricky.-The problem is that, in GHC 7.8+, the instance of type-level (==) for *-is not recursive. Thus, it's impossible, say, to get (Maybe a == Maybe b) ~ False-from (a == b) ~ False.--There are a few ways forward:- 1) Define SEq to use our own Boolean (==) operator, instead of the built-in one.- This would work, but feels wrong.- 2) Use unsafeCoerce.-We do #2.--Also to note: because these problems don't exist in GHC 7.6, the generation of-Eq and Decide for 7.6 is entirely normal.--Note that mkCustomEqInstances makes the SDecide and SEq instances in GHC 7.8+,-but the type-level (==) instance in GHC 7.6. This is perhaps poor design, but-it reduces the amount of CPP noise.--}---- | Produce a representation and singleton for the collection of types given.------ A datatype @Rep@ is created, with one constructor per type in the declared--- universe. When this type is promoted by the singletons library, the--- constructors become full types in @*@, not just promoted data constructors.--- --- For example,--- --- > $(singletonStar [''Nat, ''Bool, ''Maybe])--- --- generates the following:--- --- > data Rep = Nat | Bool | Maybe Rep deriving (Eq, Show, Read)--- --- and its singleton. However, because @Rep@ is promoted to @*@, the singleton--- is perhaps slightly unexpected:--- --- > data instance Sing (a :: *) where--- > SNat :: Sing Nat--- > SBool :: Sing Bool--- > SMaybe :: SingRep a => Sing a -> Sing (Maybe a)--- --- The unexpected part is that @Nat@, @Bool@, and @Maybe@ above are the real @Nat@,--- @Bool@, and @Maybe@, not just promoted data constructors.--- --- Please note that this function is /very/ experimental. Use at your own risk.-singletonStar :: Quasi q- => [Name] -- ^ A list of Template Haskell @Name@s for types- -> q [Dec]-singletonStar names = do- kinds <- mapM getKind names- ctors <- zipWithM (mkCtor True) names kinds- let repDecl = DataD [] repName [] ctors- [''Eq, ''Show, ''Read]- fakeCtors <- zipWithM (mkCtor False) names kinds- eqInstances <- mkCustomEqInstances fakeCtors- singletonDecls <- singDataD True [] repName [] fakeCtors- [''Show, ''Read-#if __GLASGOW_HASKELL__ < 707- , ''Eq-#endif- ]- return $ repDecl :- eqInstances ++- singletonDecls- where -- get the kinds of the arguments to the tycon with the given name- getKind :: Quasi q => Name -> q [Kind]- getKind name = do- info <- reifyWithWarning name- case info of- TyConI (DataD (_:_) _ _ _ _) ->- fail "Cannot make a representation of a constrainted data type"- TyConI (DataD [] _ tvbs _ _) ->- return $ map extractTvbKind tvbs- TyConI (NewtypeD (_:_) _ _ _ _) ->- fail "Cannot make a representation of a constrainted newtype"- TyConI (NewtypeD [] _ tvbs _ _) ->- return $ map extractTvbKind tvbs- TyConI (TySynD _ tvbs _) ->- return $ map extractTvbKind tvbs- PrimTyConI _ n _ ->- return $ replicate n StarT- _ -> fail $ "Invalid thing for representation: " ++ (show name)- - -- first parameter is whether this is a real ctor (with a fresh name)- -- or a fake ctor (when the name is actually a Haskell type)- mkCtor :: Quasi q => Bool -> Name -> [Kind] -> q Con- mkCtor real name args = do- (types, vars) <- evalForPair $ mapM kindToType args- let ctor = NormalC ((if real then reinterpret else id) name)- (map (\ty -> (NotStrict, ty)) types)- if length vars > 0- then return $ ForallC (map PlainTV vars) [] ctor- else return ctor-- -- demote a kind back to a type, accumulating any unbound parameters- kindToType :: Quasi q => Kind -> QWithAux [Name] q Type- kindToType (ForallT _ _ _) = fail "Explicit forall encountered in kind"- kindToType (AppT k1 k2) = do- t1 <- kindToType k1- t2 <- kindToType k2- return $ AppT t1 t2- kindToType (SigT _ _) = fail "Sort signature encountered in kind"- kindToType (VarT n) = do- addElement n- return $ VarT n- kindToType (ConT n) = return $ ConT n- kindToType (PromotedT _) = fail "Promoted type used as a kind"- kindToType (TupleT n) = return $ TupleT n- kindToType (UnboxedTupleT _) = fail "Unboxed tuple kind encountered"- kindToType ArrowT = return ArrowT- kindToType ListT = return ListT- kindToType (PromotedTupleT _) = fail "Promoted tuple kind encountered"- kindToType PromotedNilT = fail "Promoted nil kind encountered"- kindToType PromotedConsT = fail "Promoted cons kind encountered"- kindToType StarT = return $ ConT repName- kindToType ConstraintT =- fail $ "Cannot make a representation of a type that has " ++- "an argument of kind Constraint"- kindToType (LitT _) = fail "Literal encountered at the kind level"--mkCustomEqInstances :: Quasi q => [Con] -> q [Dec]-mkCustomEqInstances ctors = do-#if __GLASGOW_HASKELL__ >= 707- let ctorVar = error "Internal error: Equality instance inspected ctor var"- sCtors <- evalWithoutAux $ mapM (singCtor ctorVar) ctors- decideInst <- mkEqualityInstance StarT sCtors sDecideClassDesc-- a <- qNewName "a"- b <- qNewName "b"- let eqInst = InstanceD- []- (AppT (ConT ''SEq) (kindParam StarT))- [FunD '(%:==)- [Clause [VarP a, VarP b]- (NormalB $- CaseE (foldExp (VarE '(%~)) [VarE a, VarE b])- [ Match (ConP 'Proved [ConP 'Refl []])- (NormalB $ ConE 'STrue) []- , Match (ConP 'Disproved [WildP])- (NormalB $ AppE (VarE 'unsafeCoerce)- (ConE 'SFalse)) []- ]) []]]- return [decideInst, eqInst]-#else- mapM mkEqTypeInstance [(c1, c2) | c1 <- ctors, c2 <- ctors]-#endif
− Data/Singletons/Decide.hs
@@ -1,30 +0,0 @@-{-# LANGUAGE CPP #-}---------------------------------------------------------------------------------- |--- Module : Data.Singletons.Decide--- Copyright : (C) 2013 Richard Eisenberg--- License : BSD-style (see LICENSE)--- Maintainer : Richard Eisenberg (eir@cis.upenn.edu)--- Stability : experimental--- Portability : non-portable------ Defines the class 'SDecide', allowing for decidable equality over singletons.----------------------------------------------------------------------------------module Data.Singletons.Decide (- -- * The SDecide class- SDecide(..),-- -- * Supporting definitions- (:~:)(..), Void, Refuted, Decision(..)- ) where--import Data.Singletons.Types-import Data.Singletons.Core-import Data.Singletons.Void--#if __GLASGOW_HASKELL__ >= 707-import Data.Type.Equality-#endif
− Data/Singletons/Either.hs
@@ -1,107 +0,0 @@-{-# LANGUAGE TemplateHaskell, ScopedTypeVariables, TypeFamilies, GADTs,- DataKinds, PolyKinds, RankNTypes, UndecidableInstances, CPP #-}--#if __GLASGOW_HASKELL__ < 707-{-# OPTIONS_GHC -fno-warn-name-shadowing #-}-#endif---------------------------------------------------------------------------------- |--- Module : Data.Singletons.Either--- Copyright : (C) 2013 Richard Eisenberg--- License : BSD-style (see LICENSE)--- Maintainer : Richard Eisenberg (eir@cis.upenn.edu)--- Stability : experimental--- Portability : non-portable------ Defines functions and datatypes relating to the singleton for 'Either',--- including a singletons version of all the definitions in @Data.Either@.------ Because many of these definitions are produced by Template Haskell,--- it is not possible to create proper Haddock documentation. Please look--- up the corresponding operation in @Data.Either@. Also, please excuse--- the apparent repeated variable names. This is due to an interaction--- between Template Haskell and Haddock.----------------------------------------------------------------------------------module Data.Singletons.Either (- -- * The 'Either' singleton- Sing(SLeft, SRight),- -- | Though Haddock doesn't show it, the 'Sing' instance above declares- -- constructors- --- -- > SLeft :: Sing a -> Sing (Left a)- -- > SRight :: Sing b -> Sing (Right b)- - SEither,- -- | 'SEither' is a kind-restricted synonym for 'Sing':- -- @type SEither (a :: Either x y) = Sing a@-- -- * Singletons from @Data.Either@- Either_, sEither_,- -- | The preceding two definitions are derived from the function 'either' in- -- @Data.Either@. The extra underscore is to avoid name clashes with the type- -- 'Either'.- - Lefts, sLefts, Rights, sRights,- PartitionEithers, sPartitionEithers, IsLeft, sIsLeft, IsRight, sIsRight- ) where--import Data.Singletons.Core-import Data.Singletons.TH-import Data.Singletons.List--$(singletonsOnly [d|- -- | Case analysis for the 'Either' type.- -- If the value is @'Left' a@, apply the first function to @a@;- -- if it is @'Right' b@, apply the second function to @b@.- either_ :: (a -> c) -> (b -> c) -> Either a b -> c- either_ f _ (Left x) = f x- either_ _ g (Right y) = g y-- -- | Extracts from a list of 'Either' all the 'Left' elements- -- All the 'Left' elements are extracted in order.-- lefts :: [Either a b] -> [a]- lefts [] = []- lefts (Left x : xs) = x : lefts xs- lefts (Right _ : xs) = lefts xs-- -- | Extracts from a list of 'Either' all the 'Right' elements- -- All the 'Right' elements are extracted in order.-- rights :: [Either a b] -> [b]- rights [] = []- rights (Left _ : xs) = rights xs- rights (Right x : xs) = x : rights xs-- -- | Partitions a list of 'Either' into two lists- -- All the 'Left' elements are extracted, in order, to the first- -- component of the output. Similarly the 'Right' elements are extracted- -- to the second component of the output.-- partitionEithers :: [Either a b] -> ([a],[b])- partitionEithers es = partitionEithers_aux ([], []) es-- partitionEithers_aux :: ([a],[b]) -> [Either a b] -> ([a],[b])- partitionEithers_aux (as,bs) [] = (reverse as,reverse bs)- partitionEithers_aux (as,bs) (Left a : es) =- partitionEithers_aux (a : as, bs) es- partitionEithers_aux (as,bs) (Right b : es) =- partitionEithers_aux (as, b : bs) es-- -- | Return `True` if the given value is a `Left`-value, `False` otherwise.- --- -- /Since: 4.7.0.0/- isLeft :: Either a b -> Bool- isLeft (Left _) = True- isLeft (Right _) = False-- -- | Return `True` if the given value is a `Right`-value, `False` otherwise.- --- -- /Since: 4.7.0.0/- isRight :: Either a b -> Bool- isRight (Left _) = False- isRight (Right _) = True- |])
− Data/Singletons/Eq.hs
@@ -1,75 +0,0 @@-{-# LANGUAGE TypeOperators, DataKinds, PolyKinds, TypeFamilies,- RankNTypes, FlexibleContexts, TemplateHaskell,- UndecidableInstances, GADTs, CPP #-}---------------------------------------------------------------------------------- |--- Module : Data.Singletons.Eq--- Copyright : (C) 2013 Richard Eisenberg--- License : BSD-style (see LICENSE)--- Maintainer : Richard Eisenberg (eir@cis.upenn.edu)--- Stability : experimental--- Portability : non-portable------ Defines the SEq singleton version of the Eq type class.-----------------------------------------------------------------------------------module Data.Singletons.Eq (- SEq(..),- type (==), (:==), (:/=)- ) where--import Data.Singletons.Util-import Data.Singletons.Bool-import Data.Singletons.Singletons-import Data.Singletons.Core-import GHC.TypeLits ( Nat, Symbol )-import Unsafe.Coerce -- for TypeLits instances--#if __GLASGOW_HASKELL__ >= 707--import Data.Proxy-import Data.Type.Equality---- | A re-export of the type-level @(==)@ that conforms to the singletons naming--- convention.-type a :== b = a == b--#else-import Data.Singletons.Types-import Data.Singletons.Promote--type family (a :: k) :== (b :: k) :: Bool-type a == b = a :== b--#endif--type a :/= b = Not (a :== b)---- | The singleton analogue of 'Eq'. Unlike the definition for 'Eq', it is required--- that instances define a body for '(%:==)'. You may also supply a body for '(%:/=)'.-class (kparam ~ 'KProxy) => SEq (kparam :: KProxy k) where- -- | Boolean equality on singletons- (%:==) :: forall (a :: k) (b :: k). Sing a -> Sing b -> Sing (a :== b)-- -- | Boolean disequality on singletons- (%:/=) :: forall (a :: k) (b :: k). Sing a -> Sing b -> Sing (a :/= b)- a %:/= b = sNot (a %:== b)--#if __GLASGOW_HASKELL__ < 707-$(promoteEqInstances basicTypes) -- these instances are in Data.Type.Equality-#endif- -$(singEqInstancesOnly basicTypes)---- need instances for TypeLits kinds-instance SEq ('KProxy :: KProxy Nat) where- (SNat a) %:== (SNat b)- | a == b = unsafeCoerce STrue- | otherwise = unsafeCoerce SFalse--instance SEq ('KProxy :: KProxy Symbol) where- (SSym a) %:== (SSym b)- | a == b = unsafeCoerce STrue- | otherwise = unsafeCoerce SFalse
− Data/Singletons/List.hs
@@ -1,70 +0,0 @@-{-# LANGUAGE CPP, TypeOperators, DataKinds, PolyKinds, TypeFamilies,- TemplateHaskell, GADTs, UndecidableInstances #-}--#if __GLASGOW_HASKELL__ < 707-{-# OPTIONS_GHC -fno-warn-name-shadowing #-}-#endif---------------------------------------------------------------------------------- |--- Module : Data.Singletons.List--- Copyright : (C) 2013 Richard Eisenberg--- License : BSD-style (see LICENSE)--- Maintainer : Richard Eisenberg (eir@cis.upenn.edu)--- Stability : experimental--- Portability : non-portable------ Defines functions and datatypes relating to the singleton for '[]',--- including a singletons version of a few of the definitions in @Data.List@.------ Because many of these definitions are produced by Template Haskell,--- it is not possible to create proper Haddock documentation. Please look--- up the corresponding operation in @Data.List@. Also, please excuse--- the apparent repeated variable names. This is due to an interaction--- between Template Haskell and Haddock.----------------------------------------------------------------------------------module Data.Singletons.List (- -- * The singleton for lists- Sing(SNil, SCons),- -- | Though Haddock doesn't show it, the 'Sing' instance above declares- -- constructors- --- -- > SNil :: Sing '[]- -- > SCons :: Sing (h :: k) -> Sing (t :: [k]) -> Sing (h ': t)-- SList,- -- | 'SList' is a kind-restricted synonym for 'Sing': @type SList (a :: [k]) = Sing a@- - Head, Tail, sHead, sTail,- (:++), (%:++),- Reverse, sReverse- ) where--import Data.Singletons.Core-import Data.Singletons-import Data.Singletons.Singletons--$(singletonsOnly [d|- (++) :: [a] -> [a] -> [a]- [] ++ a = a- (h:t) ++ a = h:(t ++ a)-- head :: [a] -> a- head (a : _) = a- head [] = error "Data.Singletons.List.head: empty list"-- tail :: [a] -> [a]- tail (_ : t) = t- tail [] = error "Data.Singletons.List.tail: empty list"-- reverse :: [a] -> [a]- reverse list = reverse_aux [] list-- reverse_aux :: [a] -> [a] -> [a]- reverse_aux acc [] = acc- reverse_aux acc (h : t) = reverse_aux (h : acc) t- |])--
− Data/Singletons/Maybe.hs
@@ -1,120 +0,0 @@-{-# LANGUAGE TemplateHaskell, ScopedTypeVariables, TypeFamilies,- DataKinds, PolyKinds, UndecidableInstances, GADTs,- RankNTypes, CPP #-}--#if __GLASGOW_HASKELL__ < 707-{-# OPTIONS_GHC -fno-warn-name-shadowing #-}-#endif---------------------------------------------------------------------------------- |--- Module : Data.Singletons.Maybe--- Copyright : (C) 2013 Richard Eisenberg--- License : BSD-style (see LICENSE)--- Maintainer : Richard Eisenberg (eir@cis.upenn.edu)--- Stability : experimental--- Portability : non-portable------ Defines functions and datatypes relating to the singleton for 'Maybe',--- including a singletons version of all the definitions in @Data.Maybe@.------ Because many of these definitions are produced by Template Haskell,--- it is not possible to create proper Haddock documentation. Please look--- up the corresponding operation in @Data.Maybe@. Also, please excuse--- the apparent repeated variable names. This is due to an interaction--- between Template Haskell and Haddock.-----------------------------------------------------------------------------------module Data.Singletons.Maybe (- -- The 'Maybe' singleton- - Sing(SNothing, SJust),- -- | Though Haddock doesn't show it, the 'Sing' instance above declares- -- constructors- --- -- > SNothing :: Sing Nothing- -- > SJust :: Sing a -> Sing (Just a)-- SMaybe,- -- | 'SBool' is a kind-restricted synonym for 'Sing': @type SMaybe (a :: Maybe k) = Sing a@-- -- * Singletons from @Data.Maybe@-- Maybe_, sMaybe_,- -- | The preceding two definitions are derived from the function 'maybe' in- -- @Data.Maybe@. The extra underscore is to avoid name clashes with the type- -- 'Maybe'.- - IsJust, sIsJust, IsNothing, sIsNothing,- FromJust, sFromJust, FromMaybe, sFromMaybe, MaybeToList, sMaybeToList,- ListToMaybe, sListToMaybe, CatMaybes, sCatMaybes, MapMaybe, sMapMaybe- ) where--import Data.Singletons.Core-import Data.Singletons-import Data.Singletons.TH-import Data.Singletons.List--$(singletonsOnly [d|- -- | The 'maybe' function takes a default value, a function, and a 'Maybe'- -- value. If the 'Maybe' value is 'Nothing', the function returns the- -- default value. Otherwise, it applies the function to the value inside- -- the 'Just' and returns the result.- maybe_ :: b -> (a -> b) -> Maybe a -> b- maybe_ n _ Nothing = n- maybe_ _ f (Just x) = f x-- -- | The 'isJust' function returns 'True' iff its argument is of the- -- form @Just _@.- isJust :: Maybe a -> Bool- isJust Nothing = False- isJust (Just _) = True-- -- | The 'isNothing' function returns 'True' iff its argument is 'Nothing'.- isNothing :: Maybe a -> Bool- isNothing Nothing = True- isNothing (Just _) = False-- -- | The 'fromJust' function extracts the element out of a 'Just' and- -- throws an error if its argument is 'Nothing'.- fromJust :: Maybe a -> a- fromJust Nothing = error "Maybe.fromJust: Nothing" -- yuck- fromJust (Just x) = x-- -- | The 'fromMaybe' function takes a default value and and 'Maybe'- -- value. If the 'Maybe' is 'Nothing', it returns the default values;- -- otherwise, it returns the value contained in the 'Maybe'.- fromMaybe :: a -> Maybe a -> a- fromMaybe d Nothing = d- fromMaybe _ (Just v) = v-- -- | The 'maybeToList' function returns an empty list when given- -- 'Nothing' or a singleton list when not given 'Nothing'.- maybeToList :: Maybe a -> [a]- maybeToList Nothing = []- maybeToList (Just x) = [x]-- -- | The 'listToMaybe' function returns 'Nothing' on an empty list- -- or @'Just' a@ where @a@ is the first element of the list.- listToMaybe :: [a] -> Maybe a- listToMaybe [] = Nothing- listToMaybe (a:_) = Just a-- -- | The 'catMaybes' function takes a list of 'Maybe's and returns- -- a list of all the 'Just' values. - catMaybes :: [Maybe a] -> [a]- catMaybes [] = []- catMaybes (Just x : xs) = x : catMaybes xs- catMaybes (Nothing : xs) = catMaybes xs-- -- | The 'mapMaybe' function is a version of 'map' which can throw- -- out elements. In particular, the functional argument returns- -- something of type @'Maybe' b@. If this is 'Nothing', no element- -- is added on to the result list. If it just @'Just' b@, then @b@ is- -- included in the result list.- mapMaybe :: (a -> Maybe b) -> [a] -> [b]- mapMaybe _ [] = []- mapMaybe f (x:xs) = maybeToList (f x) ++ (mapMaybe f xs)- |])
− Data/Singletons/Prelude.hs
@@ -1,102 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Data.Singletons.Prelude--- Copyright : (C) 2013 Richard Eisenberg--- License : BSD-style (see LICENSE)--- Maintainer : Richard Eisenberg (eir@cis.upenn.edu)--- Stability : experimental--- Portability : non-portable------ Mimics the Haskell Prelude, but with singleton types. Includes the basic--- singleton definitions. Note: This is currently very incomplete!------ Because many of these definitions are produced by Template Haskell, it is--- not possible to create proper Haddock documentation. Also, please excuse--- the apparent repeated variable names. This is due to an interaction between--- Template Haskell and Haddock.----------------------------------------------------------------------------------module Data.Singletons.Prelude (- -- * Basic singleton definitions- module Data.Singletons,- - Sing(SFalse, STrue, SNil, SCons, SJust, SNothing, SLeft, SRight, SLT, SEQ, SGT,- STuple0, STuple2, STuple3, STuple4, STuple5, STuple6, STuple7),- -- | Though Haddock doesn't show it, the 'Sing' instance above includes- -- the following instances- --- -- > data instance Sing (a :: Bool) where- -- > SFalse :: Sing False- -- > STrue :: Sing True- -- >- -- > data instance Sing (a :: [k]) where- -- > SNil :: Sing '[]- -- > SCons :: Sing (h :: k) -> Sing (t :: [k]) -> Sing (h ': t)- -- >- -- > data instance Sing (a :: Maybe k) where- -- > SNothing :: Sing Nothing- -- > SJust :: Sing (a :: k) -> Sing (Just a)- -- >- -- > data instance Sing (a :: Either x y) where- -- > SLeft :: Sing (a :: x) -> Sing (Left a)- -- > SRight :: Sing (b :: y) -> Sing (Right b)- -- >- -- > data instance Sing (a :: Ordering) where- -- > SLT :: Sing LT- -- > SEQ :: Sing EQ- -- > SGT :: Sing GT- -- >- -- > data instance Sing (a :: ()) where- -- > STuple0 :: Sing '()- -- >- -- > data instance Sing (z :: (a, b)) where- -- > STuple2 :: Sing a -> Sing b -> Sing '(a, b)- -- >- -- > data instance Sing (z :: (a, b, c)) where- -- > STuple3 :: Sing a -> Sing b -> Sing c -> Sing '(a, b, c)- -- >- -- > data instance Sing (z :: (a, b, c, d)) where- -- > STuple4 :: Sing a -> Sing b -> Sing c -> Sing d -> Sing '(a, b, c, d)- -- >- -- > data instance Sing (z :: (a, b, c, d, e)) where- -- > STuple5 :: Sing a -> Sing b -> Sing c -> Sing d -> Sing e -> Sing '(a, b, c, d, e)- -- >- -- > data instance Sing (z :: (a, b, c, d, e, f)) where- -- > STuple6 :: Sing a -> Sing b -> Sing c -> Sing d -> Sing e -> Sing f- -- > -> Sing '(a, b, c, d, e, f)- -- >- -- > data instance Sing (z :: (a, b, c, d, e, f, g)) where- -- > STuple7 :: Sing a -> Sing b -> Sing c -> Sing d -> Sing e -> Sing f- -- > -> Sing g -> Sing '(a, b, c, d, e, f, g)-- -- * Singleton type synonyms-- -- | These synonyms are all kind-restricted synonyms of 'Sing'.- -- For example 'SBool' requires an argument of kind 'Bool'.- SBool, SList, SMaybe, SEither,- STuple0, STuple2, STuple3, STuple4, STuple5, STuple6, STuple7,-- -- * Functions working with 'Bool'- If, sIf, Not, sNot, (:&&), (:||), (%:&&), (%:||),-- -- * Functions working with lists- Head, Tail, (:++), (%:++),-- -- * Singleton equality- module Data.Singletons.Eq,-- -- * Other datatypes- Maybe_, sMaybe_,- Either_, sEither_,- Fst, sFst, Snd, sSnd, Curry, sCurry, Uncurry, sUncurry- ) where--import Data.Singletons-import Data.Singletons.Bool-import Data.Singletons.List-import Data.Singletons.Maybe-import Data.Singletons.Either-import Data.Singletons.Tuple-import Data.Singletons.Eq-import Data.Singletons.Core
− Data/Singletons/Promote.hs
@@ -1,689 +0,0 @@-{- Data/Singletons/Promote.hs--(c) Richard Eisenberg 2013-eir@cis.upenn.edu--This file contains functions to promote term-level constructs to the-type level. It is an internal module to the singletons package.--}--{-# LANGUAGE TemplateHaskell, CPP #-}-{-# OPTIONS_GHC -fwarn-incomplete-patterns #-}--module Data.Singletons.Promote where--import Language.Haskell.TH hiding ( Q, cxt )-import Language.Haskell.TH.Syntax ( falseName, trueName, Quasi(..) )-import Data.Singletons.Util-import GHC.Exts (Any)-import GHC.TypeLits (Symbol)-import Prelude hiding (exp)-import qualified Data.Map as Map-import qualified Data.Set as Set-import Control.Monad-import Data.List--anyTypeName, boolName, andName, tyEqName, repName, ifName,- headName, tailName, symbolName :: Name-anyTypeName = ''Any-boolName = ''Bool-andName = mkName "&&"-#if __GLASGOW_HASKELL__ >= 707-tyEqName = mkName "=="-#else-tyEqName = mkName ":=="-#endif-repName = mkName "Rep"-ifName = mkName "If"-headName = mkName "Head"-tailName = mkName "Tail"-symbolName = ''Symbol--falseTy :: Type-falseTy = promoteDataCon falseName--trueTy :: Type-trueTy = promoteDataCon trueName--boolTy :: Type-boolTy = ConT boolName--andTy :: Type-andTy = promoteVal andName--ifTyFam :: Type-ifTyFam = ConT ifName--headTyFam :: Type-headTyFam = ConT headName--tailTyFam :: Type-tailTyFam = ConT tailName--promoteInfo :: Quasi q => Info -> q [Dec]-promoteInfo (ClassI _dec _instances) =- fail "Promotion of class info not supported"-promoteInfo (ClassOpI _name _ty _className _fixity) =- fail "Promotion of class members info not supported"-promoteInfo (TyConI dec) = evalWithoutAux $ promoteDec Map.empty dec-promoteInfo (FamilyI _dec _instances) =- fail "Promotion of type family info not yet supported" -- KindFams-promoteInfo (PrimTyConI _name _numArgs _unlifted) =- fail "Promotion of primitive type constructors not supported"-promoteInfo (DataConI _name _ty _tyname _fixity) =- fail $ "Promotion of individual constructors not supported; " ++- "promote the type instead"-promoteInfo (VarI _name _ty _mdec _fixity) =- fail "Promotion of value info not supported"-promoteInfo (TyVarI _name _ty) =- fail "Promotion of type variable info not supported"--promoteDataCon :: Name -> Type-promoteDataCon name- | Just degree <- tupleNameDegree_maybe name- = PromotedTupleT degree-- | otherwise- = PromotedT name--promoteValName :: Name -> Name-promoteValName n- | nameBase n == "undefined" = anyTypeName- | otherwise = upcase n--promoteVal :: Name -> Type-promoteVal = ConT . promoteValName--promoteType :: Quasi q => Type -> q Kind--- We don't need to worry about constraints: they are used to express--- static guarantees at runtime. But, because we don't need to do--- anything special to keep static guarantees at compile time, we don't--- need to promote them.-promoteType (ForallT _tvbs _ ty) = promoteType ty -- ForallKinds-promoteType (VarT name) = return $ VarT name-promoteType (ConT name) = return $- case nameBase name of- "TypeRep" -> StarT- "String" -> ConT symbolName- x | x == nameBase repName -> StarT- | otherwise -> ConT name-promoteType (TupleT n) = return $ TupleT n-promoteType (UnboxedTupleT _n) = fail "Promotion of unboxed tuples not supported"-promoteType ArrowT = return ArrowT-promoteType ListT = return ListT-promoteType (AppT (AppT ArrowT (ForallT (_:_) _ _)) _) =- fail "Cannot promote types of rank above 1."-promoteType (AppT ty1 ty2) = do- k1 <- promoteType ty1- k2 <- promoteType ty2- return $ AppT k1 k2-promoteType (SigT _ty _) = fail "Cannot promote type of kind other than *"-promoteType (LitT _) = fail "Cannot promote a type-level literal"-promoteType (PromotedT _) = fail "Cannot promote a promoted data constructor"-promoteType (PromotedTupleT _) = fail "Cannot promote tuples that are already promoted"-promoteType PromotedNilT = fail "Cannot promote a nil that is already promoted"-promoteType PromotedConsT = fail "Cannot promote a cons that is already promoted"-promoteType StarT = fail "* used as a type"-promoteType ConstraintT = fail "Constraint used as a type"---- a table to keep track of variable->type mappings-type TypeTable = Map.Map Name Type---- | Promote every declaration given to the type level, retaining the originals.-promote :: Quasi q => q [Dec] -> q [Dec]-promote qdec = do- decls <- qdec- (promDecls, _) <- promoteDecs decls- return $ decls ++ promDecls---- | Promote each declaration, discarding the originals.-promoteOnly :: Quasi q => q [Dec] -> q [Dec]-promoteOnly qdec = do- decls <- qdec- (promDecls, _) <- promoteDecs decls- return promDecls--checkForRep :: Quasi q => [Name] -> q ()-checkForRep names =- when (any ((== nameBase repName) . nameBase) names)- (fail $ "A data type named <<Rep>> is a special case.\n" ++- "Promoting it will not work as expected.\n" ++- "Please choose another name for your data type.")--checkForRepInDecls :: Quasi q => [Dec] -> q ()-checkForRepInDecls decls =- checkForRep (map extractNameFromDec decls)- where extractNameFromDec :: Dec -> Name- extractNameFromDec (DataD _ name _ _ _) = name- extractNameFromDec (NewtypeD _ name _ _ _) = name- extractNameFromDec (TySynD name _ _) = name- extractNameFromDec (FamilyD _ name _ _) = name- extractNameFromDec _ = mkName "NotRep"---- Promote a list of declarations; returns the promoted declarations--- and a list of names of declarations without accompanying type signatures.--- (This list is needed by singletons to strike such definitions.)---- Promoting declarations proceeds in two stages:--- 1) Promote everything except type signatures--- 2) Promote type signatures. This must be done in a second pass because--- a function type signature gets promoted to a type family declaration.--- Although function signatures do not differentiate between uniform parameters--- and non-uniform parameters, type family declarations do. We need--- to process a function's definition to get the count of non-uniform--- parameters before producing the type family declaration.--- At this point, any function written without a type signature is rejected--- and removed.-promoteDecs :: Quasi q => [Dec] -> q ([Dec], [Name])-promoteDecs decls = do- checkForRepInDecls decls- let vartbl = Map.empty- (newDecls, table) <- evalForPair $ mapM (promoteDec vartbl) decls- (declss, namess) <- mapAndUnzipM (promoteDec' table) decls- let moreNewDecls = concat declss- names = concat namess- noTypeSigs = Set.toList $ Set.difference (Map.keysSet $-#if __GLASGOW_HASKELL__ >= 707- Map.filter ((>= 0) . fst) table)-#else- Map.filter (>= 0) table)-#endif- (Set.fromList names)- noTypeSigsPro = map promoteValName noTypeSigs- newDecls' = foldl (\bad_decls name ->- filter (not . (containsName name)) bad_decls)- (concat newDecls) (noTypeSigs ++ noTypeSigsPro)- mapM_ (\n -> qReportWarning $ "No type binding for " ++ (show (nameBase n)) ++- "; removing all declarations including it")- noTypeSigs- return (newDecls' ++ moreNewDecls, noTypeSigs)---- | Produce instances for '(:==)' (type-level equality) from the given types-promoteEqInstances :: Quasi q => [Name] -> q [Dec]-promoteEqInstances = concatMapM promoteEqInstance---- | Produce an instance for '(:==)' (type-level equality) from the given type-promoteEqInstance :: Quasi q => Name -> q [Dec]-promoteEqInstance name = do- (_tvbs, cons) <- getDataD "I cannot make an instance of (:==:) for it." name-#if __GLASGOW_HASKELL__ >= 707- vars <- replicateM (length _tvbs) (qNewName "k")- let tyvars = map VarT vars- kind = foldType (ConT name) tyvars- inst_decs <- mkEqTypeInstance kind cons- return inst_decs-#else- let pairs = [(c1, c2) | c1 <- cons, c2 <- cons]- mapM mkEqTypeInstance pairs-#endif--#if __GLASGOW_HASKELL__ >= 707---- produce a closed type family helper and the instance--- for (:==) over the given list of ctors-mkEqTypeInstance :: Quasi q => Kind -> [Con] -> q [Dec]-mkEqTypeInstance kind cons = do- helperName <- newUniqueName "Equals"- aName <- qNewName "a"- bName <- qNewName "b"- true_branches <- mapM mk_branch cons- false_branch <- false_case- let closedFam = ClosedTypeFamilyD helperName- [ KindedTV aName kind- , KindedTV bName kind ]- (Just boolTy)- (true_branches ++ [false_branch])- eqInst = TySynInstD tyEqName (TySynEqn [ SigT (VarT aName) kind- , SigT (VarT bName) kind ]- (foldType (ConT helperName)- [VarT aName, VarT bName]))- return [closedFam, eqInst]-- where mk_branch :: Quasi q => Con -> q TySynEqn- mk_branch con = do- let (name, numArgs) = extractNameArgs con- lnames <- replicateM numArgs (qNewName "a")- rnames <- replicateM numArgs (qNewName "b")- let lvars = map VarT lnames- rvars = map VarT rnames- ltype = foldType (PromotedT name) lvars- rtype = foldType (PromotedT name) rvars- results = zipWith (\l r -> foldType (ConT tyEqName) [l, r]) lvars rvars- result = tyAll results- return $ TySynEqn [ltype, rtype] result-- false_case :: Quasi q => q TySynEqn- false_case = do- lvar <- qNewName "a"- rvar <- qNewName "b"- return $ TySynEqn [SigT (VarT lvar) kind, SigT (VarT rvar) kind] falseTy-- tyAll :: [Type] -> Type -- "all" at the type level- tyAll [] = trueTy- tyAll [one] = one- tyAll (h:t) = foldType andTy [h, (tyAll t)]--#else---- produce the type instance for (:==) for the given pair of constructors-mkEqTypeInstance :: Quasi q => (Con, Con) -> q Dec-mkEqTypeInstance (c1, c2) =- if c1 == c2- then do- let (name, numArgs) = extractNameArgs c1- lnames <- replicateM numArgs (qNewName "a")- rnames <- replicateM numArgs (qNewName "b")- let lvars = map VarT lnames- rvars = map VarT rnames- return $ TySynInstD- tyEqName- [foldType (PromotedT name) lvars,- foldType (PromotedT name) rvars]- (tyAll (zipWith (\l r -> foldType (ConT tyEqName) [l, r])- lvars rvars))- else do- let (lname, lNumArgs) = extractNameArgs c1- (rname, rNumArgs) = extractNameArgs c2- lnames <- replicateM lNumArgs (qNewName "a")- rnames <- replicateM rNumArgs (qNewName "b")- return $ TySynInstD- tyEqName- [foldType (PromotedT lname) (map VarT lnames),- foldType (PromotedT rname) (map VarT rnames)]- falseTy- where tyAll :: [Type] -> Type -- "all" at the type level- tyAll [] = trueTy- tyAll [one] = one- tyAll (h:t) = foldType andTy [h, (tyAll t)]--#endif---- keeps track of the number of non-uniform parameters to promoted values--- and all of the instance equations for those values-#if __GLASGOW_HASKELL__ >= 707-type PromoteTable = Map.Map Name (Int, [TySynEqn])-#else-type PromoteTable = Map.Map Name Int-#endif-type PromoteQ q = QWithAux PromoteTable q---- used when a type is declared as a type synonym, not a type family--- no need to declare "type family ..." for these-typeSynonymFlag :: Int-typeSynonymFlag = -1--promoteDec :: Quasi q => TypeTable -> Dec -> PromoteQ q [Dec]-promoteDec vars (FunD name clauses) = do- let proName = promoteValName name- vars' = Map.insert name (promoteVal name) vars- numArgs = getNumPats (head clauses) -- count the parameters- -- Haskell requires all clauses to have the same number of parameters- (eqns, instDecls) <- evalForPair $- mapM (promoteClause vars' proName) clauses-#if __GLASGOW_HASKELL__ >= 707- addBinding name (numArgs, eqns) -- remember the number of parameters and the eqns- return instDecls-#else- addBinding name numArgs -- remember the number of parameters- return $ eqns ++ instDecls-#endif- where getNumPats :: Clause -> Int- getNumPats (Clause pats _ _) = length pats-promoteDec vars (ValD pat body decs) = do- -- see also the comment for promoteTopLevelPat- when (length decs > 0)- (fail $ "Promotion of global variable with <<where>> clause " ++- "not yet supported")- (rhs, decls) <- evalForPair $ promoteBody vars body- (lhss, decls') <- evalForPair $ promoteTopLevelPat pat- if any (flip containsName rhs) (map lhsName lhss)- then -- definition is recursive. This means an infinite value.- fail "Promotion of infinite terms not yet supported"- else do -- definition is not recursive; just use "type" decls-#if __GLASGOW_HASKELL__ >= 707- mapM_ (flip addBinding (typeSynonymFlag, [])) (map lhsRawName lhss)-#else- mapM_ (flip addBinding typeSynonymFlag) (map lhsRawName lhss)-#endif- return $ (map (\(LHS _ nm hole) -> TySynD nm [] (hole rhs)) lhss) ++- decls ++ decls'-promoteDec vars (DataD cxt name tvbs ctors derivings) = - promoteDataD vars cxt name tvbs ctors derivings-promoteDec vars (NewtypeD cxt name tvbs ctor derivings) =- promoteDataD vars cxt name tvbs [ctor] derivings-promoteDec _vars (TySynD _name _tvbs _ty) =- fail "Promotion of type synonym declaration not yet supported"-promoteDec _vars (ClassD _cxt _name _tvbs _fundeps _decs) =- fail "Promotion of class declaration not yet supported"-promoteDec _vars (InstanceD _cxt _ty _decs) =- fail "Promotion of instance declaration not yet supported"-promoteDec _vars (SigD _name _ty) = return [] -- handle in promoteDec'-promoteDec _vars (ForeignD _fgn) =- fail "Promotion of foreign function declaration not yet supported"-promoteDec _vars (InfixD fixity name)- | isUpcase name = return [] -- automatic: promoting a type or data ctor- | otherwise = return [InfixD fixity (promoteValName name)] -- value-promoteDec _vars (PragmaD _prag) =- fail "Promotion of pragmas not yet supported"-promoteDec _vars (FamilyD _flavour _name _tvbs _mkind) =- fail "Promotion of type and data families not yet supported"-promoteDec _vars (DataInstD _cxt _name _tys _ctors _derivings) =- fail "Promotion of data instances not yet supported"-promoteDec _vars (NewtypeInstD _cxt _name _tys _ctors _derivings) =- fail "Promotion of newtype instances not yet supported"-#if __GLASGOW_HASKELL__ >= 707-promoteDec _vars (RoleAnnotD _name _roles) =- return [] -- silently ignore role annotations, as they're harmless here-promoteDec _vars (ClosedTypeFamilyD _name _tvs _mkind _eqns) =- fail "Promotion of closed type families not yet supported"-promoteDec _vars (TySynInstD _name _eqn) =-#else-promoteDec _vars (TySynInstD _name _lhs _rhs) =-#endif- fail "Promotion of type synonym instances not yet supported"---- only need to check if the datatype derives Eq. The rest is automatic.-promoteDataD :: Quasi q => TypeTable -> Cxt -> Name -> [TyVarBndr] -> [Con] ->- [Name] -> PromoteQ q [Dec]-promoteDataD _vars _cxt _name _tvbs ctors derivings =- if any (\n -> (nameBase n) == "Eq") derivings- then do-#if __GLASGOW_HASKELL__ >= 707- kvs <- replicateM (length _tvbs) (qNewName "k")- inst_decs <- mkEqTypeInstance (foldType (ConT _name) (map VarT kvs)) ctors- return inst_decs-#else- let pairs = [ (c1, c2) | c1 <- ctors, c2 <- ctors ]- mapM mkEqTypeInstance pairs-#endif- else return [] -- the actual promotion is automatic---- second pass through declarations to deal with type signatures--- returns the new declarations and the list of names that have been--- processed-promoteDec' :: Quasi q => PromoteTable -> Dec -> q ([Dec], [Name])-promoteDec' tab (SigD name ty) = case Map.lookup name tab of- Nothing -> fail $ "Type declaration is missing its binding: " ++ (show name)-#if __GLASGOW_HASKELL__ >= 707- Just (numArgs, eqns) -> -#else- Just numArgs ->-#endif- -- if there are no args, then use a type synonym, not a type family- -- in the type synonym case, we ignore the type signature- if numArgs == typeSynonymFlag then return $ ([], [name]) else do - k <- promoteType ty- let ks = unravel k- (argKs, resultKs) = splitAt numArgs ks -- divide by uniformity- resultK <- ravel resultKs -- rebuild the arrow kind- tyvarNames <- mapM qNewName (replicate (length argKs) "a")-#if __GLASGOW_HASKELL__ >= 707- return ([ClosedTypeFamilyD (promoteValName name)- (zipWith KindedTV tyvarNames argKs)- (Just resultK)- eqns], [name])-#else- return ([FamilyD TypeFam- (promoteValName name)- (zipWith KindedTV tyvarNames argKs)- (Just resultK)], [name])-#endif- where unravel :: Kind -> [Kind] -- get argument kinds from an arrow kind- unravel (AppT (AppT ArrowT k1) k2) =- let ks = unravel k2 in k1 : ks- unravel k = [k]- - ravel :: Quasi q => [Kind] -> q Kind- ravel [] = fail "Internal error: raveling nil"- ravel [k] = return k- ravel (h:t) = do- k <- ravel t- return $ (AppT (AppT ArrowT h) k)-promoteDec' _ _ = return ([], [])--#if __GLASGOW_HASKELL__ >= 707-promoteClause :: Quasi q => TypeTable -> Name -> Clause -> QWithDecs q TySynEqn-#else-promoteClause :: Quasi q => TypeTable -> Name -> Clause -> QWithDecs q Dec-#endif-promoteClause vars _name (Clause pats body []) = do- -- promoting the patterns creates variable bindings. These are passed- -- to the function promoted the RHS- (types, vartbl) <- evalForPair $ mapM promotePat pats- let vars' = Map.union vars vartbl- ty <- promoteBody vars' body-#if __GLASGOW_HASKELL__ >= 707- return $ TySynEqn types ty-#else- return $ TySynInstD _name types ty-#endif-promoteClause _ _ (Clause _ _ (_:_)) =- fail "A <<where>> clause in a function definition is not yet supported"---- the LHS of a top-level expression is a name and "type with hole"--- the hole is filled in by the RHS-data TopLevelLHS = LHS { lhsRawName :: Name -- the unpromoted name- , lhsName :: Name- , lhsHole :: Type -> Type- }---- Treatment of top-level patterns is different from other patterns--- because type families have type patterns as their LHS. However,--- it is not possible to use type patterns at the top level, so we--- have to use other techniques.-promoteTopLevelPat :: Quasi q => Pat -> QWithDecs q [TopLevelLHS]-promoteTopLevelPat (LitP _) = fail "Cannot declare a global literal."-promoteTopLevelPat (VarP name) = return [LHS name (promoteValName name) id]-promoteTopLevelPat (TupP pats) = case length pats of- 0 -> return [] -- unit as LHS of pattern... ignore- 1 -> fail "1-tuple encountered during top-level pattern promotion"- n -> promoteTopLevelPat (ConP (tupleDataName n) pats)-promoteTopLevelPat (UnboxedTupP _) =- fail "Promotion of unboxed tuples not supported"---- to promote a constructor pattern, we need to create extraction type--- families to pull out the individual arguments of the constructor-promoteTopLevelPat (ConP name pats) = do- ctorInfo <- reifyWithWarning name- (ctorType, argTypes) <- extractTypes ctorInfo- when (length argTypes /= length pats) $- fail $ "Inconsistent data constructor pattern: " ++ (show name) ++ " " ++- (show pats)- kind <- promoteType ctorType- argKinds <- mapM promoteType argTypes- extractorNames <- replicateM (length pats) (newUniqueName "Extract")-- varName <- qNewName "a"- zipWithM_ (\nm arg -> addElement $ FamilyD TypeFam- nm- [KindedTV varName kind]- (Just arg))- extractorNames argKinds- componentNames <- replicateM (length pats) (qNewName "a")- zipWithM_ (\extractorName componentName ->- addElement $ mkTyFamInst extractorName- [foldType (promoteDataCon name)- (map VarT componentNames)]- (VarT componentName))- extractorNames componentNames-- -- now we have the extractor families. Use the appropriate families- -- in the "holes"- promotedPats <- mapM promoteTopLevelPat pats- return $ concat $- zipWith (\lhslist extractor ->- map (\(LHS raw nm hole) -> LHS raw nm- (hole . (AppT (ConT extractor))))- lhslist)- promotedPats extractorNames- where extractTypes :: Quasi q => Info -> q (Type, [Type])- extractTypes (DataConI datacon _dataconTy tyname _fixity) = do- tyinfo <- reifyWithWarning tyname- extractTypesHelper datacon tyinfo- extractTypes _ = fail "Internal error: unexpected Info in extractTypes"- - extractTypesHelper :: Quasi q => Name -> Info -> q (Type, [Type])- extractTypesHelper datacon- (TyConI (DataD _cxt tyname tvbs cons _derivs)) =- let mcon = find ((== datacon) . fst . extractNameArgs) cons in- case mcon of- Nothing -> fail $ "Internal error reifying " ++ (show datacon)- Just con -> return (foldType (ConT tyname)- (map (VarT . extractTvbName) tvbs),- extractConArgs con)- extractTypesHelper datacon- (TyConI (NewtypeD cxt tyname tvbs con derivs)) =- extractTypesHelper datacon (TyConI (DataD cxt tyname tvbs [con] derivs))- extractTypesHelper datacon _ =- fail $ "Cannot promote data constructor " ++ (show datacon)-- extractConArgs :: Con -> [Type]- extractConArgs = ctor1Case (\_ tys -> tys)-promoteTopLevelPat (InfixP l name r) = promoteTopLevelPat (ConP name [l, r])-promoteTopLevelPat (UInfixP _ _ _) =- fail "Unresolved infix constructors not supported"-promoteTopLevelPat (ParensP _) = - fail "Unresolved infix constructors not supported"-promoteTopLevelPat (TildeP pat) = do- qReportWarning "Lazy pattern converted into regular pattern in promotion"- promoteTopLevelPat pat-promoteTopLevelPat (BangP pat) = do- qReportWarning "Strict pattern converted into regular pattern in promotion"- promoteTopLevelPat pat-promoteTopLevelPat (AsP _name _pat) =- fail "Promotion of aliased patterns at top level not yet supported"-promoteTopLevelPat WildP = return []-promoteTopLevelPat (RecP _ _) =- fail "Promotion of record patterns at top level not yet supported"---- must do a similar trick as what is in the ConP case, but this is easier--- because Lib defined Head and Tail-promoteTopLevelPat (ListP pats) = do- promotedPats <- mapM promoteTopLevelPat pats- return $ concat $ snd $- mapAccumL (\extractFn lhss ->- ((AppT tailTyFam) . extractFn,- map (\(LHS raw nm hole) ->- LHS raw nm (hole . (AppT headTyFam) . extractFn)) lhss))- id promotedPats-promoteTopLevelPat (SigP pat _) = do- qReportWarning $ "Promotion of explicit type annotation in pattern " ++- "not yet supported."- promoteTopLevelPat pat-promoteTopLevelPat (ViewP _ _) =- fail "Promotion of view patterns not yet supported"--type TypesQ q = QWithAux TypeTable q---- promotes a term pattern into a type pattern, accumulating variable--- binding in the auxiliary TypeTable-promotePat :: Quasi q => Pat -> TypesQ q Type-promotePat (LitP lit) = promoteLit lit-promotePat (VarP name) = do- tyVar <- qNewName (nameBase name)- addBinding name (VarT tyVar)- return $ VarT tyVar-promotePat (TupP pats) = do- types <- mapM promotePat pats- let baseTup = PromotedTupleT (length types)- tup = foldType baseTup types- return tup-promotePat (UnboxedTupP _) = fail "Unboxed tuples not supported"-promotePat (ConP name pats) = do- types <- mapM promotePat pats- let tyCon = foldType (promoteDataCon name) types- return tyCon-promotePat (InfixP pat1 name pat2) = promotePat (ConP name [pat1, pat2])-promotePat (UInfixP _ _ _) = fail "Unresolved infix constructions not supported"-promotePat (ParensP _) = fail "Unresolved infix constructions not supported"-promotePat (TildeP pat) = do- qReportWarning "Lazy pattern converted into regular pattern in promotion"- promotePat pat-promotePat (BangP pat) = do- qReportWarning "Strict pattern converted into regular pattern in promotion"- promotePat pat-promotePat (AsP name pat) = do- ty <- promotePat pat- addBinding name ty- return ty-promotePat WildP = do- name <- qNewName "z"- return $ VarT name-promotePat (RecP _ _) = fail "Promotion of record patterns not yet supported"-promotePat (ListP pats) = do- types <- mapM promotePat pats- return $ foldr (\h t -> AppT (AppT PromotedConsT h) t) PromotedNilT types-promotePat (SigP pat _) = do- qReportWarning $ "Promotion of explicit type annotation in pattern " ++- "not yet supported"- promotePat pat-promotePat (ViewP _ _) = fail "View patterns not yet supported"---- promoting a body may produce auxiliary declarations. Accumulate these.-type QWithDecs q = QWithAux [Dec] q--promoteBody :: Quasi q => TypeTable -> Body -> QWithDecs q Type-promoteBody vars (NormalB exp) = promoteExp vars exp-promoteBody _vars (GuardedB _) =- fail "Promoting guards in patterns not yet supported"--promoteExp :: Quasi q => TypeTable -> Exp -> QWithDecs q Type-promoteExp vars (VarE name) = case Map.lookup name vars of- Just ty -> return ty- Nothing -> return $ promoteVal name-promoteExp _vars (ConE name) = return $ promoteDataCon name-promoteExp _vars (LitE lit) = promoteLit lit-promoteExp vars (AppE exp1 exp2) = do- ty1 <- promoteExp vars exp1- ty2 <- promoteExp vars exp2- return $ AppT ty1 ty2-promoteExp vars (InfixE mexp1 exp mexp2) =- case (mexp1, mexp2) of- (Nothing, Nothing) -> promoteExp vars exp- (Just exp1, Nothing) -> promoteExp vars (AppE exp exp1)- (Nothing, Just _exp2) ->- fail "Promotion of right-only sections not yet supported"- (Just exp1, Just exp2) -> promoteExp vars (AppE (AppE exp exp1) exp2)-promoteExp _vars (UInfixE _ _ _) =- fail "Promotion of unresolved infix operators not supported"-promoteExp _vars (ParensE _) = fail "Promotion of unresolved parens not supported"-promoteExp _vars (LamE _pats _exp) =- fail "Promotion of lambda expressions not yet supported"-promoteExp _vars (LamCaseE _alts) =- fail "Promotion of lambda-case expressions not yet supported"-promoteExp vars (TupE exps) = do- tys <- mapM (promoteExp vars) exps- let tuple = PromotedTupleT (length tys)- tup = foldType tuple tys- return tup-promoteExp _vars (UnboxedTupE _) = fail "Promotion of unboxed tuples not supported"-promoteExp vars (CondE bexp texp fexp) = do- tys <- mapM (promoteExp vars) [bexp, texp, fexp]- return $ foldType ifTyFam tys-promoteExp _vars (MultiIfE _alts) =- fail "Promotion of multi-way if not yet supported"-promoteExp _vars (LetE _decs _exp) =- fail "Promotion of let statements not yet supported"-promoteExp _vars (CaseE _exp _matches) =- fail "Promotion of case statements not yet supported"-promoteExp _vars (DoE _stmts) = fail "Promotion of do statements not supported"-promoteExp _vars (CompE _stmts) =- fail "Promotion of list comprehensions not yet supported"-promoteExp _vars (ArithSeqE _) = fail "Promotion of ranges not supported"-promoteExp vars (ListE exps) = do- tys <- mapM (promoteExp vars) exps- return $ foldr (\ty lst -> AppT (AppT PromotedConsT ty) lst) PromotedNilT tys-promoteExp _vars (SigE _exp _ty) =- fail "Promotion of explicit type annotations not yet supported"-promoteExp _vars (RecConE _name _fields) =- fail "Promotion of record construction not yet supported"-promoteExp _vars (RecUpdE _exp _fields) =- fail "Promotion of record updates not yet supported"--promoteLit :: Monad m => Lit -> m Type-promoteLit (IntegerL n)- | n >= 0 = return $ LitT (NumTyLit n)- | otherwise = fail ("Promoting negative integers not supported: " ++ (show n))-promoteLit (StringL str) = return $ LitT (StrTyLit str)-promoteLit lit =- fail ("Only string and natural number literals can be promoted: " ++ show lit)
− Data/Singletons/Singletons.hs
@@ -1,740 +0,0 @@-{- Data/Singletons/Singletons.hs--(c) Richard Eisenberg 2013-eir@cis.upenn.edu--This file contains functions to refine constructs to work with singleton-types. It is an internal module to the singletons package.--}-{-# LANGUAGE TemplateHaskell, CPP, TupleSections #-}-{-# OPTIONS_GHC -fwarn-incomplete-patterns #-}--module Data.Singletons.Singletons where--import Prelude hiding ( exp )-import Language.Haskell.TH hiding ( cxt )-import Language.Haskell.TH.Syntax (falseName, trueName, Quasi(..))-import Data.Singletons.Util-import Data.Singletons.Promote-import qualified Data.Map as Map-import Control.Monad-import Control.Applicative-import Data.Singletons.Types--#if __GLASGOW_HASKELL__ >= 707-import Data.Proxy-import Data.Type.Equality-#endif---- map to track bound variables-type ExpTable = Map.Map Name Exp---- translating a type gives a type with a hole in it,--- represented here as a function-type TypeFn = Type -> Type---- a list of argument types extracted from a type application-type TypeContext = [Type]--singFamilyName, singIName, singMethName, demoteRepName, singKindClassName, - sEqClassName, sEqMethName, sconsName, snilName, sIfName, undefinedName,- kProxyDataName, kProxyTypeName, someSingTypeName, someSingDataName,- nilName, consName, sListName, eqName, sDecideClassName, sDecideMethName,- provedName, disprovedName, reflName, toSingName, fromSingName, listName :: Name-singFamilyName = mkName "Sing"-singIName = mkName "SingI"-singMethName = mkName "sing"-toSingName = mkName "toSing"-fromSingName = mkName "fromSing"-demoteRepName = mkName "DemoteRep"-singKindClassName = mkName "SingKind"-sEqClassName = mkName "SEq"-sEqMethName = mkName "%:=="-sIfName = mkName "sIf"-undefinedName = 'undefined-sconsName = mkName "SCons"-snilName = mkName "SNil" -kProxyDataName = 'KProxy-kProxyTypeName = ''KProxy-someSingTypeName = mkName "SomeSing"-someSingDataName = mkName "SomeSing"-nilName = '[]-consName = '(:)-listName = ''[]-sListName = mkName "SList"-eqName = ''Eq-sDecideClassName = mkName "SDecide"-sDecideMethName = mkName "%~"-provedName = 'Proved-disprovedName = 'Disproved-reflName = 'Refl--mkTupleName :: Int -> Name-mkTupleName n = mkName $ "STuple" ++ (show n)--singFamily :: Type-singFamily = ConT singFamilyName--singKindConstraint :: Kind -> Pred-singKindConstraint k = ClassP singKindClassName [kindParam k]--demote :: Type-demote = ConT demoteRepName--singDataConName :: Name -> Name-singDataConName nm- | nm == nilName = snilName- | nm == consName = sconsName- | Just degree <- tupleNameDegree_maybe nm = mkTupleName degree- | otherwise = prefixUCName "S" ":%" nm--singTyConName :: Name -> Name-singTyConName name- | name == listName = sListName- | Just degree <- tupleNameDegree_maybe name = mkTupleName degree- | otherwise = prefixUCName "S" ":%" name--singClassName :: Name -> Name-singClassName = singTyConName--singDataCon :: Name -> Exp-singDataCon = ConE . singDataConName--singValName :: Name -> Name-singValName n- | nameBase n == "undefined" = undefinedName- | otherwise = (prefixLCName "s" "%") $ upcase n--singVal :: Name -> Exp-singVal = VarE . singValName--kindParam :: Kind -> Type-kindParam k = SigT (ConT kProxyDataName) (AppT (ConT kProxyTypeName) k)---- | Generate singleton definitions from a type that is already defined.--- For example, the singletons package itself uses------ > $(genSingletons [''Bool, ''Maybe, ''Either, ''[]])------ to generate singletons for Prelude types.-genSingletons :: Quasi q => [Name] -> q [Dec]-genSingletons names = do- checkForRep names- concatMapM (singInfo <=< reifyWithWarning) names--singInfo :: Quasi q => Info -> q [Dec]-singInfo (ClassI _dec _instances) =- fail "Singling of class info not supported"-singInfo (ClassOpI _name _ty _className _fixity) =- fail "Singling of class members info not supported"-singInfo (TyConI dec) = singDec dec-singInfo (FamilyI _dec _instances) =- fail "Singling of type family info not yet supported" -- KindFams-singInfo (PrimTyConI _name _numArgs _unlifted) =- fail "Singling of primitive type constructors not supported"-singInfo (DataConI _name _ty _tyname _fixity) =- fail $ "Singling of individual constructors not supported; " ++- "single the type instead"-singInfo (VarI _name _ty _mdec _fixity) =- fail "Singling of value info not supported"-singInfo (TyVarI _name _ty) =- fail "Singling of type variable info not supported"---- refine a constructor. the first parameter is the type variable that--- the singleton GADT is parameterized by--- runs in the QWithDecs monad because auxiliary declarations are produced-singCtor :: Quasi q => Type -> Con -> QWithDecs q Con -singCtor a = ctorCases- -- monomorphic case- (\name types -> do- let sName = singDataConName name- sCon = singDataCon name- pCon = promoteDataCon name- indexNames <- replicateM (length types) (qNewName "n")- let indices = map VarT indexNames- kinds <- mapM promoteType types- args <- buildArgTypes types indices- let tvbs = zipWith KindedTV indexNames kinds- kindedIndices = zipWith SigT indices kinds-- -- SingI instance- addElement $ InstanceD (map (ClassP singIName . listify) indices)- (AppT (ConT singIName)- (foldType pCon kindedIndices))- [ValD (VarP singMethName)- (NormalB $ foldExp sCon (replicate (length types)- (VarE singMethName)))- []]-- return $ ForallC tvbs- [EqualP a (foldType pCon indices)]- (NormalC sName $ map (NotStrict,) args))-- -- polymorphic case- (\_tvbs cxt ctor -> case cxt of- _:_ -> fail "Singling of constrained constructors not yet supported"- [] -> singCtor a ctor) -- polymorphic constructors are handled just- -- like monomorphic ones -- the polymorphism in- -- the kind is automatic- where buildArgTypes :: Quasi q => [Type] -> [Type] -> q [Type]- buildArgTypes types indices = do- typeFns <- mapM singType types- return $ zipWith id typeFns indices---- | Make promoted and singleton versions of all declarations given, retaining--- the original declarations.--- See <http://www.cis.upenn.edu/~eir/packages/singletons/README.html> for--- further explanation.-singletons :: Quasi q => q [Dec] -> q [Dec]-singletons = (>>= singDecs True)---- | Make promoted and singleton versions of all declarations given, discarding--- the original declarations.-singletonsOnly :: Quasi q => q [Dec] -> q [Dec]-singletonsOnly = (>>= singDecs False)---- first parameter says whether or not to include original decls-singDecs :: Quasi q => Bool -> [Dec] -> q [Dec]-singDecs originals decls = do- (promDecls, badNames) <- promoteDecs decls- -- need to remove the bad names returned from promoteDecs- newDecls <- mapM singDec- (filter (\dec ->- not $ or (map (\f -> f dec)- (map containsName badNames))) decls)- return $ (if originals then (decls ++) else id) $ promDecls ++ (concat newDecls)--singDec :: Quasi q => Dec -> q [Dec]-singDec (FunD name clauses) = do- let sName = singValName name- vars = Map.singleton name (VarE sName)- listify <$> FunD sName <$> (mapM (singClause vars) clauses)-singDec (ValD _ (GuardedB _) _) =- fail "Singling of definitions of values with a pattern guard not yet supported"-singDec (ValD _ _ (_:_)) =- fail "Singling of definitions of values with a <<where>> clause not yet supported"-singDec (ValD pat (NormalB exp) []) = do- (sPat, vartbl) <- evalForPair $ singPat TopLevel pat- sExp <- singExp vartbl exp- return [ValD sPat (NormalB sExp) []]-singDec (DataD (_:_) _ _ _ _) =- fail "Singling of constrained datatypes not supported"-singDec (DataD cxt name tvbs ctors derivings) =- singDataD False cxt name tvbs ctors derivings-singDec (NewtypeD cxt name tvbs ctor derivings) =- singDataD False cxt name tvbs [ctor] derivings-singDec (TySynD _name _tvbs _ty) =- fail "Singling of type synonyms not yet supported"-singDec (ClassD _cxt _name _tvbs _fundeps _decs) =- fail "Singling of class declaration not yet supported"-singDec (InstanceD _cxt _ty _decs) =- fail "Singling of class instance not yet supported"-singDec (SigD name ty) = do- tyTrans <- singType ty- return [SigD (singValName name) (tyTrans (promoteVal name))]-singDec (ForeignD fgn) =- let name = extractName fgn in do- qReportWarning $ "Singling of foreign functions not supported -- " ++- (show name) ++ " ignored"- return []- where extractName :: Foreign -> Name- extractName (ImportF _ _ _ n _) = n- extractName (ExportF _ _ n _) = n-singDec (InfixD fixity name)- | isUpcase name = return [InfixD fixity (singDataConName name)]- | otherwise = return [InfixD fixity (singValName name)]-singDec (PragmaD _prag) = do- qReportWarning "Singling of pragmas not supported"- return []-singDec (FamilyD _flavour _name _tvbs _mkind) =- fail "Singling of type and data families not yet supported"-singDec (DataInstD _cxt _name _tys _ctors _derivings) = - fail "Singling of data instances not yet supported"-singDec (NewtypeInstD _cxt _name _tys _ctor _derivings) =- fail "Singling of newtype instances not yet supported"-#if __GLASGOW_HASKELL__ >= 707-singDec (RoleAnnotD _name _roles) =- return [] -- silently ignore role annotations, as they're harmless-singDec (ClosedTypeFamilyD _name _tvs _mkind _eqns) =- fail "Singling of closed type families not yet supported"-singDec (TySynInstD _name _eqns) =-#else-singDec (TySynInstD _name _lhs _rhs) =-#endif- fail "Singling of type family instances not yet supported"---- | Create instances of 'SEq' and type-level '(:==)' for each type in the list-singEqInstances :: Quasi q => [Name] -> q [Dec]-singEqInstances = concatMapM singEqInstance---- | Create instance of 'SEq' and type-level '(:==)' for the given type-singEqInstance :: Quasi q => Name -> q [Dec]-singEqInstance name = do- promotion <- promoteEqInstance name- dec <- singEqualityInstance sEqClassDesc name- return $ dec : promotion---- | Create instances of 'SEq' (only -- no instance for '(:==)', which 'SEq' generally--- relies on) for each type in the list-singEqInstancesOnly :: Quasi q => [Name] -> q [Dec]-singEqInstancesOnly = concatMapM singEqInstanceOnly---- | Create instances of 'SEq' (only -- no instance for '(:==)', which 'SEq' generally--- relies on) for the given type-singEqInstanceOnly :: Quasi q => Name -> q [Dec]-singEqInstanceOnly name = listify <$> singEqualityInstance sEqClassDesc name---- | Create instances of 'SDecide' for each type in the list-singDecideInstances :: Quasi q => [Name] -> q [Dec]-singDecideInstances = concatMapM singDecideInstance---- | Create instance of SDecide for the given type-singDecideInstance :: Quasi q => Name -> q [Dec]-singDecideInstance name = listify <$> singEqualityInstance sDecideClassDesc name---- generalized function for creating equality instances-singEqualityInstance :: Quasi q => EqualityClassDesc q -> Name -> q Dec-singEqualityInstance desc@(_, className, _) name = do- (tvbs, cons) <- getDataD ("I cannot make an instance of " ++- show className ++ " for it.") name- let tyvars = map (VarT . extractTvbName) tvbs- kind = foldType (ConT name) tyvars- aName <- qNewName "a"- let aVar = VarT aName- scons <- mapM (evalWithoutAux . singCtor aVar) cons- mkEqualityInstance kind scons desc---- making the SEq instance and the SDecide instance are rather similar,--- so we generalize-type EqualityClassDesc q = ((Con, Con) -> q Clause, Name, Name)-sEqClassDesc, sDecideClassDesc :: Quasi q => EqualityClassDesc q-sEqClassDesc = (mkEqMethClause, sEqClassName, sEqMethName)-sDecideClassDesc = (mkDecideMethClause, sDecideClassName, sDecideMethName)---- pass the *singleton* constructors, not the originals-mkEqualityInstance :: Quasi q => Kind -> [Con]- -> EqualityClassDesc q -> q Dec-mkEqualityInstance k ctors (mkMeth, className, methName) = do- let ctorPairs = [ (c1, c2) | c1 <- ctors, c2 <- ctors ]- methClauses <- if null ctors- then mkEmptyMethClauses- else mapM mkMeth ctorPairs- return $ InstanceD (map (\kvar -> ClassP className [kindParam kvar])- (getKindVars k))- (AppT (ConT className)- (kindParam k))- [FunD methName methClauses]- where getKindVars :: Kind -> [Kind]- getKindVars (AppT l r) = getKindVars l ++ getKindVars r- getKindVars (VarT x) = [VarT x]- getKindVars (ConT _) = []- getKindVars StarT = []- getKindVars other =- error ("getKindVars sees an unusual kind: " ++ show other)-- mkEmptyMethClauses :: Quasi q => q [Clause]- mkEmptyMethClauses = do- a <- qNewName "a"- return [Clause [VarP a, WildP] (NormalB (CaseE (VarE a) emptyMatches)) []]--mkEqMethClause :: Quasi q => (Con, Con) -> q Clause-mkEqMethClause (c1, c2)- | lname == rname = do- lnames <- replicateM lNumArgs (qNewName "a")- rnames <- replicateM lNumArgs (qNewName "b")- let lpats = map VarP lnames- rpats = map VarP rnames- lvars = map VarE lnames- rvars = map VarE rnames- return $ Clause- [ConP lname lpats, ConP rname rpats]- (NormalB $- allExp (zipWith (\l r -> foldExp (VarE sEqMethName) [l, r])- lvars rvars))- []- | otherwise =- return $ Clause- [ConP lname (replicate lNumArgs WildP),- ConP rname (replicate rNumArgs WildP)]- (NormalB (singDataCon falseName))- []- where allExp :: [Exp] -> Exp- allExp [] = singDataCon trueName- allExp [one] = one- allExp (h:t) = AppE (AppE (singVal andName) h) (allExp t)-- (lname, lNumArgs) = extractNameArgs c1- (rname, rNumArgs) = extractNameArgs c2--mkDecideMethClause :: Quasi q => (Con, Con) -> q Clause-mkDecideMethClause (c1, c2)- | lname == rname = - if lNumArgs == 0- then return $ Clause [ConP lname [], ConP rname []]- (NormalB (AppE (ConE provedName) (ConE reflName))) []- else do- lnames <- replicateM lNumArgs (qNewName "a")- rnames <- replicateM lNumArgs (qNewName "b")- contra <- qNewName "contra"- let lpats = map VarP lnames- rpats = map VarP rnames- lvars = map VarE lnames- rvars = map VarE rnames- return $ Clause- [ConP lname lpats, ConP rname rpats]- (NormalB $- CaseE (mkTupleExp $- zipWith (\l r -> foldExp (VarE sDecideMethName) [l, r])- lvars rvars)- ((Match (mkTuplePat (replicate lNumArgs- (ConP provedName [ConP reflName []])))- (NormalB $ AppE (ConE provedName) (ConE reflName))- []) :- [Match (mkTuplePat (replicate i WildP ++- ConP disprovedName [VarP contra] :- replicate (lNumArgs - i - 1) WildP))- (NormalB $ AppE (ConE disprovedName)- (LamE [ConP reflName []]- (AppE (VarE contra)- (ConE reflName))))- [] | i <- [0..lNumArgs-1] ]))- []- - | otherwise =- return $ Clause- [ConP lname (replicate lNumArgs WildP),- ConP rname (replicate rNumArgs WildP)]- (NormalB (AppE (ConE disprovedName) (LamCaseE emptyMatches)))- []-- where- (lname, lNumArgs) = extractNameArgs c1- (rname, rNumArgs) = extractNameArgs c2---- the first parameter is True when we're refining the special case "Rep"--- and false otherwise. We wish to consider the promotion of "Rep" to be *--- not a promoted data constructor.-singDataD :: Quasi q => Bool -> Cxt -> Name -> [TyVarBndr] -> [Con] -> [Name] -> q [Dec]-singDataD rep cxt name tvbs ctors derivings- | (_:_) <- cxt = fail "Singling of constrained datatypes is not supported"- | otherwise = do- aName <- qNewName "z"- let a = VarT aName- let tvbNames = map extractTvbName tvbs- k <- promoteType (foldType (ConT name) (map VarT tvbNames))- (ctors', ctorInstDecls) <- evalForPair $ mapM (singCtor a) ctors- - -- instance for SingKind- fromSingClauses <- mapM mkFromSingClause ctors- toSingClauses <- mapM mkToSingClause ctors- let singKindInst =- InstanceD (map (singKindConstraint . VarT) tvbNames)- (AppT (ConT singKindClassName)- (kindParam k))- [ mkTyFamInst demoteRepName- [kindParam k]- (foldType (ConT name)- (map (AppT demote . kindParam . VarT) tvbNames))- , FunD fromSingName (fromSingClauses `orIfEmpty` emptyMethod aName)- , FunD toSingName (toSingClauses `orIfEmpty` emptyMethod aName) ]- - -- SEq instance- sEqInsts <- if elem eqName derivings- then mapM (mkEqualityInstance k ctors') [sEqClassDesc, sDecideClassDesc]- else return []- - -- e.g. type SNat (a :: Nat) = Sing a- let kindedSynInst =- TySynD (singTyConName name)- [KindedTV aName k]- (AppT singFamily a)-- return $ (DataInstD [] singFamilyName [SigT a k] ctors' []) :- kindedSynInst :- singKindInst :- sEqInsts ++- ctorInstDecls- where -- in the Rep case, the names of the constructors are in the wrong scope- -- (they're types, not datacons), so we have to reinterpret them.- mkConName :: Name -> Name- mkConName = if rep then reinterpret else id-- mkFromSingClause :: Quasi q => Con -> q Clause- mkFromSingClause c = do- let (cname, numArgs) = extractNameArgs c- varNames <- replicateM numArgs (qNewName "b")- return $ Clause [ConP (singDataConName cname) (map VarP varNames)]- (NormalB $ foldExp- (ConE $ mkConName cname)- (map (AppE (VarE fromSingName) . VarE) varNames))- []-- mkToSingClause :: Quasi q => Con -> q Clause- mkToSingClause = ctor1Case $ \cname types -> do- varNames <- mapM (const $ qNewName "b") types- svarNames <- mapM (const $ qNewName "c") types- promoted <- mapM promoteType types- let recursiveCalls = zipWith mkRecursiveCall varNames promoted- return $- Clause [ConP (mkConName cname) (map VarP varNames)]- (NormalB $- multiCase recursiveCalls- (map (ConP someSingDataName . listify . VarP)- svarNames)- (AppE (ConE someSingDataName)- (foldExp (ConE (singDataConName cname))- (map VarE svarNames))))- []-- mkRecursiveCall :: Name -> Kind -> Exp- mkRecursiveCall var_name ki =- SigE (AppE (VarE toSingName) (VarE var_name))- (AppT (ConT someSingDataName) (kindParam ki))-- emptyMethod :: Name -> [Clause]- emptyMethod n = [Clause [VarP n] (NormalB $ CaseE (VarE n) emptyMatches) []]--singKind :: Quasi q => Kind -> q (Kind -> Kind)-singKind (ForallT _ _ _) =- fail "Singling of explicitly quantified kinds not yet supported"-singKind (VarT _) = fail "Singling of kind variables not yet supported"-singKind (ConT _) = fail "Singling of named kinds not yet supported"-singKind (TupleT _) = fail "Singling of tuple kinds not yet supported"-singKind (UnboxedTupleT _) = fail "Unboxed tuple used as kind"-singKind ArrowT = fail "Singling of unsaturated arrow kinds not yet supported"-singKind ListT = fail "Singling of list kinds not yet supported"-singKind (AppT (AppT ArrowT k1) k2) = do- k1fn <- singKind k1- k2fn <- singKind k2- k <- qNewName "k"- return $ \f -> AppT (AppT ArrowT (k1fn (VarT k))) (k2fn (AppT f (VarT k)))-singKind (AppT _ _) = fail "Singling of kind applications not yet supported"-singKind (SigT _ _) =- fail "Singling of explicitly annotated kinds not yet supported"-singKind (LitT _) = fail "Type literal used as kind"-singKind (PromotedT _) = fail "Promoted data constructor used as kind"-singKind (PromotedTupleT _) = fail "Promoted tuple used as kind"-singKind PromotedNilT = fail "Promoted nil used as kind"-singKind PromotedConsT = fail "Promoted cons used as kind"-singKind StarT = return $ \k -> AppT (AppT ArrowT k) StarT-singKind ConstraintT = fail "Singling of constraint kinds not yet supported"--singType :: Quasi q => Type -> q TypeFn-singType ty = do -- replace with singTypeRec [] ty after GHC bug #??? is fixed- sTypeFn <- singTypeRec [] ty- return $ \inner_ty -> liftOutForalls $ sTypeFn inner_ty-- -- the lifts all foralls to the top-level-liftOutForalls :: Type -> Type-liftOutForalls =- go [] [] []- where- go tyvars cxt args (ForallT tyvars1 cxt1 t1)- = go (reverse tyvars1 ++ tyvars) (reverse cxt1 ++ cxt) args t1- go tyvars cxt args (SigT t1 _kind) -- ignore these kind annotations, which have to be *- = go tyvars cxt args t1- go tyvars cxt args (AppT (AppT ArrowT arg1) res1)- = go tyvars cxt (arg1 : args) res1- go [] [] args t1- = mk_fun_ty (reverse args) t1- go tyvars cxt args t1- = ForallT (reverse tyvars) (reverse cxt) (mk_fun_ty (reverse args) t1)-- mk_fun_ty [] res = res- mk_fun_ty (arg1:args) res = AppT (AppT ArrowT arg1) (mk_fun_ty args res)---- the first parameter is the list of types the current type is applied to-singTypeRec :: Quasi q => TypeContext -> Type -> q TypeFn-singTypeRec (_:_) (ForallT _ _ _) =- fail "I thought this was impossible in Haskell. Email me at eir@cis.upenn.edu with your code if you see this message."-singTypeRec [] (ForallT _ [] ty) = -- Sing makes handling foralls automatic- singTypeRec [] ty-singTypeRec ctx (ForallT _tvbs cxt innerty) = do- cxt' <- singContext cxt- innerty' <- singTypeRec ctx innerty- return $ \ty -> ForallT [] cxt' (innerty' ty)-singTypeRec (_:_) (VarT _) =- fail "Singling of type variables of arrow kinds not yet supported"-singTypeRec [] (VarT _name) = - return $ \ty -> AppT singFamily ty-singTypeRec _ctx (ConT _name) = -- we don't need to process the context with Sing- return $ \ty -> AppT singFamily ty-singTypeRec _ctx (TupleT _n) = -- just like ConT- return $ \ty -> AppT singFamily ty-singTypeRec _ctx (UnboxedTupleT _n) =- fail "Singling of unboxed tuple types not yet supported"-singTypeRec ctx ArrowT = case ctx of- [ty1, ty2] -> do- t <- qNewName "t"- sty1 <- singTypeRec [] ty1- sty2 <- singTypeRec [] ty2- k1 <- promoteType ty1- return (\f -> ForallT [KindedTV t k1]- []- (AppT (AppT ArrowT (sty1 (VarT t)))- (sty2 (AppT f (VarT t)))))- _ -> fail "Internal error in Sing: converting ArrowT with improper context"-singTypeRec _ctx ListT =- return $ \ty -> AppT singFamily ty-singTypeRec ctx (AppT ty1 ty2) =- singTypeRec (ty2 : ctx) ty1 -- recur with the ty2 in the applied context-singTypeRec _ctx (SigT _ty _knd) =- fail "Singling of types with explicit kinds not yet supported"-singTypeRec _ctx (LitT _) = fail "Singling of type-level literals not yet supported"-singTypeRec _ctx (PromotedT _) =- fail "Singling of promoted data constructors not yet supported"-singTypeRec _ctx (PromotedTupleT _) =- fail "Singling of type-level tuples not yet supported"-singTypeRec _ctx PromotedNilT = fail "Singling of promoted nil not yet supported"-singTypeRec _ctx PromotedConsT = fail "Singling of type-level cons not yet supported"-singTypeRec _ctx StarT = fail "* used as type"-singTypeRec _ctx ConstraintT = fail "Constraint used as type"---- refine a constraint context-singContext :: Quasi q => Cxt -> q Cxt-singContext = mapM singPred--singPred :: Quasi q => Pred -> q Pred-singPred (ClassP name tys) = do- kis <- mapM promoteType tys- let sName = singClassName name- return $ ClassP sName (map kindParam kis)-singPred (EqualP _ty1 _ty2) =- fail "Singling of type equality constraints not yet supported"--singClause :: Quasi q => ExpTable -> Clause -> q Clause-singClause vars (Clause pats (NormalB exp) []) = do- (sPats, vartbl) <- evalForPair $ mapM (singPat Parameter) pats- let vars' = Map.union vartbl vars- sBody <- NormalB <$> singExp vars' exp- return $ Clause sPats sBody []-singClause _ (Clause _ (GuardedB _) _) =- fail "Singling of guarded patterns not yet supported"-singClause _ (Clause _ _ (_:_)) =- fail "Singling of <<where>> declarations not yet supported"--type ExpsQ q = QWithAux ExpTable q---- we need to know where a pattern is to anticipate when--- GHC's brain might explode-data PatternContext = LetBinding- | CaseStatement- | TopLevel- | Parameter- | Statement- deriving Eq--checkIfBrainWillExplode :: Quasi q => PatternContext -> ExpsQ q ()-checkIfBrainWillExplode CaseStatement = return ()-checkIfBrainWillExplode Statement = return ()-checkIfBrainWillExplode Parameter = return ()-checkIfBrainWillExplode _ =- fail $ "Can't use a singleton pattern outside of a case-statement or\n" ++- "do expression: GHC's brain will explode if you try. (Do try it!)"---- convert a pattern, building up the lexical scope as we go-singPat :: Quasi q => PatternContext -> Pat -> ExpsQ q Pat-singPat _patCxt (LitP _lit) =- fail "Singling of literal patterns not yet supported"-singPat patCxt (VarP name) =- let new = if patCxt == TopLevel then singValName name else name in do- addBinding name (VarE new)- return $ VarP new-singPat patCxt (TupP pats) =- singPat patCxt (ConP (tupleDataName (length pats)) pats)-singPat _patCxt (UnboxedTupP _pats) =- fail "Singling of unboxed tuples not supported"-singPat patCxt (ConP name pats) = do- checkIfBrainWillExplode patCxt- pats' <- mapM (singPat patCxt) pats- return $ ConP (singDataConName name) pats'-singPat patCxt (InfixP pat1 name pat2) = singPat patCxt (ConP name [pat1, pat2])-singPat _patCxt (UInfixP _ _ _) =- fail "Singling of unresolved infix patterns not supported"-singPat _patCxt (ParensP _) =- fail "Singling of unresolved paren patterns not supported"-singPat patCxt (TildeP pat) = do- pat' <- singPat patCxt pat- return $ TildeP pat'-singPat patCxt (BangP pat) = do- pat' <- singPat patCxt pat- return $ BangP pat'-singPat patCxt (AsP name pat) = do- let new = if patCxt == TopLevel then singValName name else name in do- pat' <- singPat patCxt pat- addBinding name (VarE new)- return $ AsP name pat'-singPat _patCxt WildP = return WildP-singPat _patCxt (RecP _name _fields) =- fail "Singling of record patterns not yet supported"-singPat patCxt (ListP pats) = do- checkIfBrainWillExplode patCxt- sPats <- mapM (singPat patCxt) pats- return $ foldr (\elt lst -> ConP sconsName [elt, lst]) (ConP snilName []) sPats-singPat _patCxt (SigP _pat _ty) =- fail "Singling of annotated patterns not yet supported"-singPat _patCxt (ViewP _exp _pat) =- fail "Singling of view patterns not yet supported"--singExp :: Quasi q => ExpTable -> Exp -> q Exp-singExp vars (VarE name) = case Map.lookup name vars of- Just exp -> return exp- Nothing -> return (singVal name)-singExp _vars (ConE name) = return $ singDataCon name-singExp _vars (LitE lit) = singLit lit-singExp vars (AppE exp1 exp2) = do- exp1' <- singExp vars exp1- exp2' <- singExp vars exp2- return $ AppE exp1' exp2'-singExp vars (InfixE mexp1 exp mexp2) =- case (mexp1, mexp2) of- (Nothing, Nothing) -> singExp vars exp- (Just exp1, Nothing) -> singExp vars (AppE exp exp1)- (Nothing, Just _exp2) ->- fail "Singling of right-only sections not yet supported"- (Just exp1, Just exp2) -> singExp vars (AppE (AppE exp exp1) exp2)-singExp _vars (UInfixE _ _ _) =- fail "Singling of unresolved infix expressions not supported"-singExp _vars (ParensE _) =- fail "Singling of unresolved paren expressions not supported"-singExp vars (LamE pats exp) = do- (pats', vartbl) <- evalForPair $ mapM (singPat Parameter) pats- let vars' = Map.union vartbl vars -- order matters; union is left-biased- exp' <- singExp vars' exp- return $ LamE pats' exp'-singExp _vars (LamCaseE _matches) = - fail "Singling of case expressions not yet supported"-singExp vars (TupE exps) = do- sExps <- mapM (singExp vars) exps- sTuple <- singExp vars (ConE (tupleDataName (length exps)))- return $ foldExp sTuple sExps-singExp _vars (UnboxedTupE _exps) =- fail "Singling of unboxed tuple not supported"-singExp vars (CondE bexp texp fexp) = do- exps <- mapM (singExp vars) [bexp, texp, fexp]- return $ foldExp (VarE sIfName) exps-singExp _vars (MultiIfE _alts) =- fail "Singling of multi-way if statements not yet supported"-singExp _vars (LetE _decs _exp) =- fail "Singling of let expressions not yet supported"-singExp _vars (CaseE _exp _matches) =- fail "Singling of case expressions not yet supported"-singExp _vars (DoE _stmts) =- fail "Singling of do expressions not yet supported"-singExp _vars (CompE _stmts) =- fail "Singling of list comprehensions not yet supported"-singExp _vars (ArithSeqE _range) =- fail "Singling of ranges not yet supported"-singExp vars (ListE exps) = do- sExps <- mapM (singExp vars) exps- return $ foldr (\x -> (AppE (AppE (ConE sconsName) x)))- (ConE snilName) sExps-singExp _vars (SigE _exp _ty) =- fail "Singling of annotated expressions not yet supported"-singExp _vars (RecConE _name _fields) =- fail "Singling of record construction not yet supported"-singExp _vars (RecUpdE _exp _fields) =- fail "Singling of record updates not yet supported"--singLit :: Quasi q => Lit -> q Exp-singLit lit = SigE (VarE singMethName) <$> (AppT singFamily <$> (promoteLit lit))
− Data/Singletons/TH.hs
@@ -1,89 +0,0 @@-{-# LANGUAGE ExplicitNamespaces, CPP #-}---------------------------------------------------------------------------------- |--- Module : Data.Singletons.TH--- Copyright : (C) 2013 Richard Eisenberg--- License : BSD-style (see LICENSE)--- Maintainer : Richard Eisenberg (eir@cis.upenn.edu)--- Stability : experimental--- Portability : non-portable------ This module contains everything you need to derive your own singletons via--- Template Haskell.------ TURN ON @-XScopedTypeVariables@ IN YOUR MODULE IF YOU WANT THIS TO WORK.----------------------------------------------------------------------------------module Data.Singletons.TH (- -- * Primary Template Haskell generation functions- singletons, singletonsOnly, genSingletons,- promote, promoteOnly,-- -- ** Functions to generate equality instances- promoteEqInstances, promoteEqInstance,- singEqInstances, singEqInstance,- singEqInstancesOnly, singEqInstanceOnly,- singDecideInstances, singDecideInstance,-- -- ** Utility function- cases,-- -- * Basic singleton definitions- Sing(SFalse, STrue), SingI(..), SingKind(..), KindOf, Demote,- - -- * Auxiliary definitions- -- | These definitions might be mentioned in code generated by Template Haskell,- -- so they must be in scope.- - type (==), (:==), If, sIf, (:&&), SEq(..), - Any, - SDecide(..), (:~:)(..), Void, Refuted, Decision(..),- KProxy(..), SomeSing(..)- ) where--import Data.Singletons.Singletons-import Data.Singletons.Promote-import Data.Singletons.Core-import Data.Singletons.Bool-import Data.Singletons.Eq-import Data.Singletons.Types-import Data.Singletons.Void--import GHC.Exts-import Language.Haskell.TH-import Language.Haskell.TH.Syntax ( Quasi(..) )-import Language.Haskell.TH.Desugar-import Data.Singletons.Util-import Control.Applicative--#if __GLASGOW_HASKELL__ >= 707-import Data.Type.Equality-import Data.Proxy-#endif---- | The function 'cases' generates a case expression where each right-hand side--- is identical. This may be useful if the type-checker requires knowledge of which--- constructor is used to satisfy equality or type-class constraints, but where--- each constructor is treated the same.-cases :: Quasi q- => Name -- ^ The head of the type of the scrutinee. (Like @''Maybe@ or @''Bool@.)- -> q Exp -- ^ The scrutinee, in a Template Haskell quote- -> q Exp -- ^ The body, in a Template Haskell quote- -> q Exp-cases tyName expq bodyq = do- info <- reifyWithWarning tyName- case info of- TyConI (DataD _ _ _ ctors _) -> buildCases ctors- TyConI (NewtypeD _ _ _ ctor _) -> buildCases [ctor]- _ -> fail $ "Using <<cases>> with something other than a type constructor: "- ++ (show tyName)- where buildCases ctors =- CaseE <$> expq <*>- mapM (\con -> Match (conToPat con) <$>- (NormalB <$> bodyq) <*> pure []) ctors-- conToPat :: Con -> Pat- conToPat = ctor1Case- (\name tys -> ConP name (map (const WildP) tys))
− Data/Singletons/Tuple.hs
@@ -1,61 +0,0 @@-{-# LANGUAGE TemplateHaskell, ScopedTypeVariables, DataKinds, PolyKinds,- RankNTypes, TypeFamilies, GADTs, CPP #-}--#if __GLASGOW_HASKELL__ < 707-{-# OPTIONS_GHC -fno-warn-name-shadowing #-}-#endif---------------------------------------------------------------------------------- |--- Module : Data.Singletons.Tuple--- Copyright : (C) 2013 Richard Eisenberg--- License : BSD-style (see LICENSE)--- Maintainer : Richard Eisenberg (eir@cis.upenn.edu)--- Stability : experimental--- Portability : non-portable------ Defines functions and datatypes relating to the singleton for tuples,--- including a singletons version of all the definitions in @Data.Tuple@.------ Because many of these definitions are produced by Template Haskell,--- it is not possible to create proper Haddock documentation. Please look--- up the corresponding operation in @Data.Tuple@. Also, please excuse--- the apparent repeated variable names. This is due to an interaction--- between Template Haskell and Haddock.----------------------------------------------------------------------------------module Data.Singletons.Tuple (- -- * Singleton definitions- -- | See 'Data.Singletons.Prelude.Sing' for more info.- Sing(STuple0, STuple2, STuple3, STuple4, STuple5, STuple6, STuple7),- STuple0, STuple2, STuple3, STuple4, STuple5, STuple6, STuple7,-- -- * Singletons from @Data.Tuple@- Fst, sFst, Snd, sSnd, Curry, sCurry, Uncurry, sUncurry, Swap, sSwap- ) where--import Data.Singletons.Core-import Data.Singletons.TH--$(singletonsOnly [d|- -- | Extract the first component of a pair.- fst :: (a,b) -> a- fst (x,_) = x-- -- | Extract the second component of a pair.- snd :: (a,b) -> b- snd (_,y) = y-- -- | 'curry' converts an uncurried function to a curried function.- curry :: ((a, b) -> c) -> a -> b -> c- curry f x y = f (x, y)-- -- | 'uncurry' converts a curried function to a function on pairs.- uncurry :: (a -> b -> c) -> ((a, b) -> c)- uncurry f p = f (fst p) (snd p)-- -- | Swap the components of a pair.- swap :: (a,b) -> (b,a)- swap (a,b) = (b,a)- |])
− Data/Singletons/TypeRepStar.hs
@@ -1,98 +0,0 @@-{-# LANGUAGE RankNTypes, TypeFamilies, KindSignatures, FlexibleInstances,- GADTs, UndecidableInstances, ScopedTypeVariables, DataKinds,- MagicHash, CPP, TypeOperators #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}---------------------------------------------------------------------------------- |--- Module : Data.Singletons.TypeRepStar--- Copyright : (C) 2013 Richard Eisenberg--- License : BSD-style (see LICENSE)--- Maintainer : Richard Eisenberg (eir@cis.upenn.edu)--- Stability : experimental--- Portability : non-portable------ This module defines singleton instances making 'Typeable' the singleton for--- the kind @*@. The definitions don't fully line up with what is expected--- within the singletons library, so expect unusual results!----------------------------------------------------------------------------------module Data.Singletons.TypeRepStar (- Sing(STypeRep)- -- | Here is the definition of the singleton for @*@:- --- -- > data instance Sing (a :: *) where- -- > STypeRep :: Typeable a => Sing a- --- -- Instances for 'SingI', 'SingKind', 'SEq', 'SDecide', and 'TestCoercion' are- -- also supplied.- ) where--import Data.Singletons.Core-import Data.Singletons.Types-import Data.Singletons.Eq-import Data.Typeable-import Unsafe.Coerce--#if __GLASGOW_HASKELL__ >= 707-import GHC.Exts ( Proxy# )-import Data.Type.Coercion-import Data.Proxy-#else--eqT :: (Typeable a, Typeable b) => Maybe (a :~: b)-eqT = gcast Refl--type instance (a :: *) :== (a :: *) = True--#endif--data instance Sing (a :: *) where- STypeRep :: Typeable a => Sing a--instance Typeable a => SingI (a :: *) where- sing = STypeRep-instance SingKind ('KProxy :: KProxy *) where- type DemoteRep ('KProxy :: KProxy *) = TypeRep- fromSing (STypeRep :: Sing a) = typeOf (undefined :: a)- toSing = dirty_mk_STypeRep--instance SEq ('KProxy :: KProxy *) where- (STypeRep :: Sing a) %:== (STypeRep :: Sing b) =- case (eqT :: Maybe (a :~: b)) of- Just Refl -> STrue- Nothing -> unsafeCoerce SFalse- -- the Data.Typeable interface isn't strong enough- -- to enable us to define this without unsafeCoerce--instance SDecide ('KProxy :: KProxy *) where- (STypeRep :: Sing a) %~ (STypeRep :: Sing b) =- case (eqT :: Maybe (a :~: b)) of- Just Refl -> Proved Refl- Nothing -> Disproved (\Refl -> error "Data.Typeable.eqT failed")--#if __GLASGOW_HASKELL__ >= 707--- TestEquality instance already defined, but we need this one:-instance TestCoercion Sing where- testCoercion (STypeRep :: Sing a) (STypeRep :: Sing b) =- case (eqT :: Maybe (a :~: b)) of- Just Refl -> Just Coercion- Nothing -> Nothing-#endif---- everything below here is private and dirty. Don't look!- -newtype DI = Don'tInstantiate (Typeable a => Sing a)-dirty_mk_STypeRep :: TypeRep -> SomeSing ('KProxy :: KProxy *)-dirty_mk_STypeRep rep =-#if __GLASGOW_HASKELL__ >= 707- let justLikeTypeable :: Proxy# a -> TypeRep- justLikeTypeable _ = rep- in-#else- let justLikeTypeable :: a -> TypeRep- justLikeTypeable _ = rep- in-#endif- unsafeCoerce (Don'tInstantiate STypeRep) justLikeTypeable
− Data/Singletons/Types.hs
@@ -1,55 +0,0 @@-{-# LANGUAGE PolyKinds, TypeOperators, GADTs, RankNTypes, TypeFamilies,- CPP, DataKinds #-}---------------------------------------------------------------------------------- |--- Module : Data.Singletons.Types--- Copyright : (C) 2013 Richard Eisenberg--- License : BSD-style (see LICENSE)--- Maintainer : Richard Eisenberg (eir@cis.upenn.edu)--- Stability : experimental--- Portability : non-portable------ Defines and exports types that are useful when working with singletons.--- Some of these are re-exports from @Data.Type.Equality@.-----------------------------------------------------------------------------------module Data.Singletons.Types (- Refuted, Decision(..),-#if __GLASGOW_HASKELL__ < 707- KProxy(..), Proxy(..),- (:~:)(..), gcastWith, TestEquality(..)-#endif- ) where--import Data.Singletons.Void--#if __GLASGOW_HASKELL__ < 707---- now in Data.Proxy-data KProxy (a :: *) = KProxy-data Proxy a = Proxy---- now in Data.Type.Equality-data a :~: b where- Refl :: a :~: a--gcastWith :: (a :~: b) -> ((a ~ b) => r) -> r-gcastWith Refl x = x--class TestEquality (f :: k -> *) where- testEquality :: f a -> f b -> Maybe (a :~: b)--#endif---- | Because we can never create a value of type 'Void', a function that type-checks--- at @a -> Void@ shows that objects of type @a@ can never exist. Thus, we say that--- @a@ is 'Refuted'-type Refuted a = (a -> Void)---- | A 'Decision' about a type @a@ is either a proof of existence or a proof that @a@--- cannot exist.-data Decision a = Proved a -- ^ Witness for @a@- | Disproved (Refuted a) -- ^ Proof that no @a@ exists
− Data/Singletons/Util.hs
@@ -1,274 +0,0 @@-{- Data/Singletons/Util.hs--(c) Richard Eisenberg 2013-eir@cis.upenn.edu--This file contains helper functions internal to the singletons package.-Users of the package should not need to consult this file.--}--{-# LANGUAGE CPP, TypeSynonymInstances, FlexibleInstances, RankNTypes,- TemplateHaskell, GeneralizedNewtypeDeriving,- MultiParamTypeClasses #-}-{-# OPTIONS_GHC -fwarn-incomplete-patterns #-}--module Data.Singletons.Util (- module Data.Singletons.Util,- module Language.Haskell.TH.Desugar )- where--import Prelude hiding ( exp )-import Language.Haskell.TH hiding ( Q )-import Language.Haskell.TH.Syntax ( Quasi(..) )-import Language.Haskell.TH.Desugar ( reifyWithWarning, getDataD )-import Data.Char-import Data.Data-import Control.Monad-import Control.Applicative-import Control.Monad.Writer-import qualified Data.Map as Map-import Data.Generics--mkTyFamInst :: Name -> [Type] -> Type -> Dec-mkTyFamInst name lhs rhs =-#if __GLASGOW_HASKELL__ >= 707- TySynInstD name (TySynEqn lhs rhs)-#else- TySynInstD name lhs rhs-#endif---- The list of types that singletons processes by default-basicTypes :: [Name]-basicTypes = [ ''Bool- , ''Maybe- , ''Either- , ''Ordering- , ''[]- , ''()- , ''(,)- , ''(,,)- , ''(,,,)- , ''(,,,,)- , ''(,,,,,)- , ''(,,,,,,)- ]---- like newName, but even more unique (unique across different splices)--- TH doesn't allow "newName"s to work at the top-level, so we have to--- do this trick to ensure the Extract functions are unique-newUniqueName :: Quasi q => String -> q Name-newUniqueName str = do- n <- qNewName str- return $ mkName $ show n---- like reportWarning, but generalized to any Quasi-qReportWarning :: Quasi q => String -> q ()-qReportWarning = qReport False---- extract the degree of a tuple-tupleDegree_maybe :: String -> Maybe Int-tupleDegree_maybe s = do- '(' : s1 <- return s - (commas, ")") <- return $ span (== ',') s1- let degree- | "" <- commas = 0- | otherwise = length commas + 1- return degree---- extract the degree of a tuple name-tupleNameDegree_maybe :: Name -> Maybe Int-tupleNameDegree_maybe = tupleDegree_maybe . nameBase---- reduce the four cases of a 'Con' to just two: monomorphic and polymorphic--- and convert 'StrictType' to 'Type'-ctorCases :: (Name -> [Type] -> a) -> ([TyVarBndr] -> Cxt -> Con -> a) -> Con -> a-ctorCases genFun forallFun ctor = case ctor of- NormalC name stypes -> genFun name (map snd stypes)- RecC name vstypes -> genFun name (map (\(_,_,ty) -> ty) vstypes)- InfixC (_,ty1) name (_,ty2) -> genFun name [ty1, ty2]- ForallC [] [] ctor' -> ctorCases genFun forallFun ctor'- ForallC tvbs cx ctor' -> forallFun tvbs cx ctor' ---- reduce the four cases of a 'Con' to just 1: a polymorphic Con is treated--- as a monomorphic one-ctor1Case :: (Name -> [Type] -> a) -> Con -> a-ctor1Case mono = ctorCases mono (\_ _ ctor -> ctor1Case mono ctor)---- extract the name and number of arguments to a constructor-extractNameArgs :: Con -> (Name, Int)-extractNameArgs = ctor1Case (\name tys -> (name, length tys))---- reinterpret a name. This is useful when a Name has an associated--- namespace that we wish to forget-reinterpret :: Name -> Name-reinterpret = mkName . nameBase---- is an identifier uppercase?-isUpcase :: Name -> Bool-isUpcase n = let first = head (nameBase n) in isUpper first || first == ':'---- make an identifier uppercase-upcase :: Name -> Name-upcase n =- let str = nameBase n - first = head str in- if isLetter first- then mkName ((toUpper first) : tail str)- else mkName (':' : str)---- make an identifier lowercase-locase :: Name -> Name-locase n =- let str = nameBase n- first = head str in- if isLetter first- then mkName ((toLower first) : tail str)- else mkName (tail str) -- remove the ":"---- put an uppercase prefix on a name. Takes two prefixes: one for identifiers--- and one for symbols-prefixUCName :: String -> String -> Name -> Name-prefixUCName pre tyPre n = case (nameBase n) of- (':' : rest) -> mkName (tyPre ++ rest)- alpha -> mkName (pre ++ alpha)---- put a lowercase prefix on a name. Takes two prefixes: one for identifiers--- and one for symbols-prefixLCName :: String -> String -> Name -> Name-prefixLCName pre tyPre n =- let str = nameBase n- first = head str in- if isLetter first- then mkName (pre ++ str)- else mkName (tyPre ++ str)---- extract the kind from a TyVarBndr. Returns '*' by default.-extractTvbKind :: TyVarBndr -> Kind-extractTvbKind (PlainTV _) = StarT -- FIXME: This seems wrong.-extractTvbKind (KindedTV _ k) = k---- extract the name from a TyVarBndr.-extractTvbName :: TyVarBndr -> Name-extractTvbName (PlainTV n) = n-extractTvbName (KindedTV n _) = n---- apply a type to a list of types-foldType :: Type -> [Type] -> Type-foldType = foldl AppT---- apply an expression to a list of expressions-foldExp :: Exp -> [Exp] -> Exp-foldExp = foldl AppE---- is a kind a variable?-isVarK :: Kind -> Bool-isVarK (VarT _) = True-isVarK _ = False---- tuple up a list of expressions-mkTupleExp :: [Exp] -> Exp-mkTupleExp [x] = x-mkTupleExp xs = TupE xs---- tuple up a list of patterns-mkTuplePat :: [Pat] -> Pat-mkTuplePat [x] = x-mkTuplePat xs = TupP xs---- choose the first non-empty list-orIfEmpty :: [a] -> [a] -> [a]-orIfEmpty [] x = x-orIfEmpty x _ = x---- an empty list of matches, compatible with GHC 7.6.3-emptyMatches :: [Match]-#if __GLASGOW_HASKELL__ >= 707-emptyMatches = []-#else-emptyMatches = [Match WildP (NormalB (AppE (VarE 'error) (LitE (StringL errStr)))) []]- where errStr = "Empty case reached -- this should be impossible"-#endif---- build a pattern match over several expressions, each with only one pattern-multiCase :: [Exp] -> [Pat] -> Exp -> Exp-multiCase [] [] body = body-multiCase scruts pats body =- CaseE (mkTupleExp scruts)- [Match (mkTuplePat pats) (NormalB body) []]---- a monad transformer for writing a monoid alongside returning a Q-newtype QWithAux m q a = QWA { runQWA :: WriterT m q a }- deriving (Functor, Applicative, Monad, MonadTrans)--instance (Monoid m, Monad q) => MonadWriter m (QWithAux m q) where- writer = QWA . writer- tell = QWA . tell- listen = QWA . listen . runQWA- pass = QWA . pass . runQWA---- make a Quasi instance for easy lifting-instance (Quasi q, Monoid m) => Quasi (QWithAux m q) where- qNewName = lift `comp1` qNewName- qReport = lift `comp2` qReport- qLookupName = lift `comp2` qLookupName- qReify = lift `comp1` qReify- qReifyInstances = lift `comp2` qReifyInstances- qLocation = lift qLocation- qRunIO = lift `comp1` qRunIO- qAddDependentFile = lift `comp1` qAddDependentFile-#if __GLASGOW_HASKELL__ >= 707- qReifyRoles = lift `comp1` qReifyRoles- qReifyAnnotations = lift `comp1` qReifyAnnotations- qReifyModule = lift `comp1` qReifyModule- qAddTopDecls = lift `comp1` qAddTopDecls- qAddModFinalizer = lift `comp1` qAddModFinalizer- qGetQ = lift qGetQ- qPutQ = lift `comp1` qPutQ-#endif - - qRecover exp handler = do- (result, aux) <- lift $ qRecover (evalForPair exp) (evalForPair handler)- tell aux- return result---- helper functions for composition-comp1 :: (b -> c) -> (a -> b) -> a -> c-comp1 = (.)--comp2 :: (c -> d) -> (a -> b -> c) -> a -> b -> d-comp2 f g a b = f (g a b)---- run a computation with an auxiliary monoid, discarding the monoid result-evalWithoutAux :: Quasi q => QWithAux m q a -> q a-evalWithoutAux = liftM fst . runWriterT . runQWA---- run a computation with an auxiliary monoid, returning only the monoid result-evalForAux :: Quasi q => QWithAux m q a -> q m-evalForAux = execWriterT . runQWA---- run a computation with an auxiliary monoid, return both the result--- of the computation and the monoid result-evalForPair :: Quasi q => QWithAux m q a -> q (a, m)-evalForPair = runWriterT . runQWA---- in a computation with an auxiliary map, add a binding to the map-addBinding :: (Quasi q, Ord k) => k -> v -> QWithAux (Map.Map k v) q ()-addBinding k v = tell (Map.singleton k v)---- in a computation with an auxiliar list, add an element to the list-addElement :: Quasi q => elt -> QWithAux [elt] q ()-addElement elt = tell [elt]---- does a TH structure contain a name?-containsName :: Data a => Name -> a -> Bool-containsName n = everything (||) (mkQ False (== n))---- lift concatMap into a monad-concatMapM :: Monad m => (a -> m [b]) -> [a] -> m [b]-concatMapM fn list = do- bss <- mapM fn list- return $ concat bss---- make a one-element list-listify :: a -> [a]-listify = return
− Data/Singletons/Void.hs
@@ -1,78 +0,0 @@-{- Data/Singletons/Void.hs-- A reimplementation of a Void type, copied shamelessly from Edward Kmett's void- package, but without inducing a dependency.---}--{-# LANGUAGE CPP, Trustworthy, DeriveDataTypeable, DeriveGeneric, StandaloneDeriving #-}---------------------------------------------------------------------------------- |--- Copyright : (C) 2008-2013 Edward Kmett--- License : BSD-style (see LICENSE)--- Maintainer : Richard Eisenberg (eir@cis.upenn.edu)--- Stability : experimental--- Portability : non-portable------ This module is a reimplementation of Edward Kmett's @void@ package.--- It is included within singletons to avoid depending on @void@ and all the--- packages that depends on (including @text@). If this causes problems for--- you (that singletons has its own 'Void' type), please let me (Richard Eisenberg)--- know at @eir@ at @cis.upenn.edu@.---------------------------------------------------------------------------------module Data.Singletons.Void- ( Void- , absurd- , vacuous- , vacuousM- ) where--import Control.Monad (liftM)-import Data.Ix-import Data.Data-import GHC.Generics-import Control.Exception---- | A logically uninhabited data type.-newtype Void = Void Void- deriving (Data, Typeable, Generic)--instance Eq Void where- _ == _ = True--instance Ord Void where- compare _ _ = EQ--instance Show Void where- showsPrec _ = absurd---- | Reading a 'Void' value is always a parse error, considering 'Void' as--- a data type with no constructors.-instance Read Void where- readsPrec _ _ = []---- | Since 'Void' values logically don't exist, this witnesses the logical--- reasoning tool of \"ex falso quodlibet\".-absurd :: Void -> a-absurd a = a `seq` spin a where- spin (Void b) = spin b---- | If 'Void' is uninhabited then any 'Functor' that holds only values of type 'Void'--- is holding no values.-vacuous :: Functor f => f Void -> f a-vacuous = fmap absurd---- | If 'Void' is uninhabited then any 'Monad' that holds values of type 'Void'--- is holding no values.-vacuousM :: Monad m => m Void -> m a-vacuousM = liftM absurd--instance Ix Void where- range _ = []- index _ = absurd- inRange _ = absurd- rangeSize _ = 0--instance Exception Void
README.md view
@@ -1,6 +1,8 @@-singletons 0.9.3-================+singletons 0.10+=============== +[](https://travis-ci.org/goldfirere/singletons)+ This is the README file for the singletons library. This file contains all the documentation for the definitions and functions in the library. @@ -36,8 +38,41 @@ * `RankNTypes` * `UndecidableInstances` * `FlexibleInstances`-* `EmptyCase` (for GHC 7.8) +Modules+-------++`Data.Singletons` exports all the basic singletons definitions. Import this+module if you are not using Template Haskell and wish only to define your+own singletons.++`Data.Singletons.TH` exports all the definitions needed to use the Template+Haskell code to generate new singletons.++`Data.Singletons.Prelude` re-exports `Data.Singletons` along with singleton+definitions for various Prelude types. This module is intended to export+those definitions that are exported by the real `Prelude`.++There are several modules that echo standard modules. For example,+`Data.Singletons.Maybe` exports singleton definitions for `Data.Maybe`.+These modules are: `List` (many definitions are missing), `Bool`,+`Maybe`, `Either`, `Tuple`.++`Data.Singletons.Eq` and `Data.Singletons.Decide` export type classes for+Boolean and propositional equality, respectively.++`Data.Singletons.TypeLits` exports definitions for working with `GHC.TypeLits`.+In GHC 7.6.3, `Data.Singletons.TypeLits` defines and exports `KnownNat` and+`KnownSymbol`, which are part of `GHC.TypeLits` in GHC 7.8. This makes cross-version+support a little easier.++`Data.Singletons.Void` exports a `Void` type, shamelessly copied from+Edward Kmett's `void` package, but without the great many package dependencies+in `void`.++`Data.Singletons.Types` exports a few type-level definitions that are in+`base` for GHC 7.8, but not in GHC 7.6.3. By importing this package, users+of both GHC versions can access these definitions. Functions to generate singletons --------------------------------
singletons.cabal view
@@ -1,5 +1,6 @@ name: singletons-version: 0.9.3+version: 0.10.0+ -- Remember to bump version in the Makefile as well cabal-version: >= 1.10 synopsis: A framework for generating singleton types homepage: http://www.cis.upenn.edu/~eir/packages/singletons@@ -8,7 +9,21 @@ maintainer: Richard Eisenberg <eir@cis.upenn.edu> bug-reports: https://github.com/goldfirere/singletons/issues stability: experimental-extra-source-files: README.md, CHANGES.md+tested-with: GHC ==7.6.3, GHC ==7.8.*+extra-source-files: README.md, CHANGES.md,+ tests/compile-and-dump/buildGoldenFiles.awk,+ tests/compile-and-dump/GradingClient/*.hs,+ tests/compile-and-dump/InsertionSort/*.hs,+ tests/compile-and-dump/Promote/*.hs,+ tests/compile-and-dump/Singletons/*.hs+ tests/compile-and-dump/GradingClient/*.ghc76.template,+ tests/compile-and-dump/InsertionSort/*.ghc76.template,+ tests/compile-and-dump/Promote/*.ghc76.template,+ tests/compile-and-dump/Singletons/*.ghc76.template,+ tests/compile-and-dump/GradingClient/*.ghc78.template,+ tests/compile-and-dump/InsertionSort/*.ghc78.template,+ tests/compile-and-dump/Promote/*.ghc78.template,+ tests/compile-and-dump/Singletons/*.ghc78.template license: BSD3 license-file: LICENSE build-type: Simple@@ -21,22 +36,21 @@ (<http://www.cis.upenn.edu/~eir/papers/2012/singletons/paper.pdf>) The Haddock documentation does not build with the Haddock distributed with- GHC 7.6.x, but it does build with HEAD. Please see links from the project+ GHC 7.6.x, but it does build with 7.8.1. Please see links from the project homepage to find the built documentation. source-repository this type: git location: https://github.com/goldfirere/singletons.git- tag: v0.9.3+ tag: v0.10.0 library- build-depends: - base >= 4.6 && < 5,- mtl >= 2.1.1,- template-haskell,- containers >= 0.5,- syb >= 0.3,- th-desugar >= 1.2+ hs-source-dirs: src+ build-depends: base >= 4.6 && < 5,+ mtl >= 2.1.1,+ template-haskell,+ containers >= 0.5,+ th-desugar >= 1.2 default-language: Haskell2010 exposed-modules: Data.Singletons, Data.Singletons.CustomStar,@@ -50,27 +64,29 @@ Data.Singletons.Eq, Data.Singletons.Prelude, Data.Singletons.Types,+ Data.Singletons.TypeLits, Data.Singletons.Decide, Data.Singletons.Void other-modules: Data.Singletons.Promote, Data.Singletons.Singletons, Data.Singletons.Util,- Data.Singletons.Core+ Data.Singletons.Instances --- This DOES NOT WORK with GHC HEAD because of -dynamic-too problems--- test-suite compile--- type: exitcode-stdio-1.0--- ghc-options: -Wall -Werror -main-is Test.Main--- default-language: Haskell2010--- main-is: Test/Main.hs+ ghc-options: -Wall --- build-depends:--- base >= 4.6 && < 5,--- constraints >= 0.3,--- containers >= 0.5,--- syb >= 0.3,--- mtl >= 2.1.1,--- th-desugar >= 1.2,--- template-haskell- +test-suite singletons-test-suite+ type: exitcode-stdio-1.0+ hs-source-dirs: src, tests+ ghc-options: -Wall+ default-language: Haskell2010+ main-is: SingletonsTestSuite.hs+ other-modules: SingletonsTestSuiteUtils++ build-depends: base >= 4.6 && < 5,+ constraints,+ filepath >= 1.3,+ process >= 1.1,+ tasty >= 0.6,+ tasty-golden >= 2.2,+ Cabal >= 1.16
+ src/Data/Singletons.hs view
@@ -0,0 +1,182 @@+{-# LANGUAGE MagicHash, RankNTypes, PolyKinds, GADTs, DataKinds,+ FlexibleContexts, CPP, TypeFamilies #-}++-----------------------------------------------------------------------------+-- |+-- Module : Data.Singletons+-- Copyright : (C) 2013 Richard Eisenberg+-- License : BSD-style (see LICENSE)+-- Maintainer : Richard Eisenberg (eir@cis.upenn.edu)+-- Stability : experimental+-- Portability : non-portable+--+-- This module exports the basic definitions to use singletons. For routine+-- use, consider importing 'Data.Singletons.Prelude', which exports constructors+-- for singletons based on types in the @Prelude@.+--+-- You may also want to read+-- <http://www.cis.upenn.edu/~eir/packages/singletons/README.html> and the+-- original paper presenting this library, available at+-- <http://www.cis.upenn.edu/~eir/papers/2012/singletons/paper.pdf>.+--+----------------------------------------------------------------------------++#if __GLASGOW_HASKELL__ < 707+ -- optimizing instances of SDecide cause GHC to die (#8467)+{-# OPTIONS_GHC -O0 #-}+#endif++module Data.Singletons (+ -- * Main singleton definitions++ Sing,+ -- | See also 'Data.Singletons.Prelude.Sing' for exported constructors++ SingI(..), SingKind(..),++ -- * Working with singletons+ KindOf, Demote,+ SingInstance(..), SomeSing(..),+ singInstance, withSingI, withSomeSing, singByProxy,++#if __GLASGOW_HASKELL__ >= 707+ singByProxy#,+#endif+ withSing, singThat,++ -- * Auxiliary functions+ bugInGHC,+ KProxy(..), Proxy(..)+ ) where++import Unsafe.Coerce++#if __GLASGOW_HASKELL__ >= 707+import GHC.Exts ( Proxy# )+import Data.Proxy+#else+import Data.Singletons.Types+#endif++-- | Convenient synonym to refer to the kind of a type variable:+-- @type KindOf (a :: k) = ('KProxy :: KProxy k)@+type KindOf (a :: k) = ('KProxy :: KProxy k)++----------------------------------------------------------------------+---- Sing & friends --------------------------------------------------+----------------------------------------------------------------------+ +-- | The singleton kind-indexed data family.+data family Sing (a :: k)++-- | A 'SingI' constraint is essentially an implicitly-passed singleton.+-- If you need to satisfy this constraint with an explicit singleton, please+-- see 'withSingI'.+class SingI (a :: k) where+ -- | Produce the singleton explicitly. You will likely need the @ScopedTypeVariables@+ -- extension to use this method the way you want.+ sing :: Sing a++-- | The 'SingKind' class is essentially a /kind/ class. It classifies all kinds+-- for which singletons are defined. The class supports converting between a singleton+-- type and the base (unrefined) type which it is built from.+class (kparam ~ 'KProxy) => SingKind (kparam :: KProxy k) where+ -- | Get a base type from a proxy for the promoted kind. For example,+ -- @DemoteRep ('KProxy :: KProxy Bool)@ will be the type @Bool@.+ type DemoteRep kparam :: *++ -- | Convert a singleton to its unrefined version.+ fromSing :: Sing (a :: k) -> DemoteRep kparam++ -- | Convert an unrefined type to an existentially-quantified singleton type.+ toSing :: DemoteRep kparam -> SomeSing kparam++-- | Convenient abbreviation for 'DemoteRep':+-- @type Demote (a :: k) = DemoteRep ('KProxy :: KProxy k)@+type Demote (a :: k) = DemoteRep ('KProxy :: KProxy k)++-- | An /existentially-quantified/ singleton. This type is useful when you want a+-- singleton type, but there is no way of knowing, at compile-time, what the type+-- index will be. To make use of this type, you will generally have to use a+-- pattern-match:+--+-- > foo :: Bool -> ...+-- > foo b = case toSing b of+-- > SomeSing sb -> {- fancy dependently-typed code with sb -}+--+-- An example like the one above may be easier to write using 'withSomeSing'.+data SomeSing (kproxy :: KProxy k) where+ SomeSing :: Sing (a :: k) -> SomeSing ('KProxy :: KProxy k)++----------------------------------------------------------------------+---- SingInstance ----------------------------------------------------+----------------------------------------------------------------------+ +-- | A 'SingInstance' wraps up a 'SingI' instance for explicit handling.+data SingInstance (a :: k) where+ SingInstance :: SingI a => SingInstance a++-- dirty implementation of explicit-to-implicit conversion+newtype DI a = Don'tInstantiate (SingI a => SingInstance a)++-- | Get an implicit singleton (a 'SingI' instance) from an explicit one.+singInstance :: forall (a :: k). Sing a -> SingInstance a+singInstance s = with_sing_i SingInstance+ where+ with_sing_i :: (SingI a => SingInstance a) -> SingInstance a+ with_sing_i si = unsafeCoerce (Don'tInstantiate si) s++----------------------------------------------------------------------+---- Convenience -----------------------------------------------------+----------------------------------------------------------------------++-- | Convenience function for creating a context with an implicit singleton+-- available.+withSingI :: Sing n -> (SingI n => r) -> r+withSingI sn r =+ case singInstance sn of+ SingInstance -> r++-- | Convert a normal datatype (like 'Bool') to a singleton for that datatype,+-- passing it into a continuation.+withSomeSing :: SingKind ('KProxy :: KProxy k)+ => DemoteRep ('KProxy :: KProxy k) -- ^ The original datatype+ -> (forall (a :: k). Sing a -> r) -- ^ Function expecting a singleton+ -> r+withSomeSing x f =+ case toSing x of+ SomeSing x' -> f x'++-- | A convenience function useful when we need to name a singleton value+-- multiple times. Without this function, each use of 'sing' could potentially+-- refer to a different singleton, and one has to use type signatures (often+-- with @ScopedTypeVariables@) to ensure that they are the same.+withSing :: SingI a => (Sing a -> b) -> b+withSing f = f sing++-- | A convenience function that names a singleton satisfying a certain+-- property. If the singleton does not satisfy the property, then the function+-- returns 'Nothing'. The property is expressed in terms of the underlying+-- representation of the singleton.+singThat :: forall (a :: k). (SingKind ('KProxy :: KProxy k), SingI a)+ => (Demote a -> Bool) -> Maybe (Sing a)+singThat p = withSing $ \x -> if p (fromSing x) then Just x else Nothing++-- | Allows creation of a singleton when a proxy is at hand.+singByProxy :: SingI a => proxy a -> Sing a+singByProxy _ = sing++#if __GLASGOW_HASKELL__ >= 707+-- | Allows creation of a singleton when a @proxy#@ is at hand.+singByProxy# :: SingI a => Proxy# a -> Sing a+singByProxy# _ = sing+#endif++-- | GHC 7.8 sometimes warns about incomplete pattern matches when no such+-- patterns are possible, due to GADT constraints.+-- See the bug report at <https://ghc.haskell.org/trac/ghc/ticket/3927>.+-- In such cases, it's useful to have a catch-all pattern that then has+-- 'bugInGHC' as its right-hand side.+bugInGHC :: forall a. a+bugInGHC = error "Bug encountered in GHC -- this should never happen"+
+ src/Data/Singletons/Bool.hs view
@@ -0,0 +1,102 @@+{-# LANGUAGE TemplateHaskell, DataKinds, PolyKinds, TypeFamilies, TypeOperators,+ GADTs, CPP #-}++#if __GLASGOW_HASKELL__ < 707+{-# OPTIONS_GHC -fno-warn-name-shadowing #-}+#endif++-----------------------------------------------------------------------------+-- |+-- Module : Data.Singletons.Bool+-- Copyright : (C) 2013 Richard Eisenberg+-- License : BSD-style (see LICENSE)+-- Maintainer : Richard Eisenberg (eir@cis.upenn.edu)+-- Stability : experimental+-- Portability : non-portable+--+-- Defines functions and datatypes relating to the singleton for 'Bool',+-- including a singletons version of all the definitions in @Data.Bool@.+--+-- Because many of these definitions are produced by Template Haskell,+-- it is not possible to create proper Haddock documentation. Please look+-- up the corresponding operation in @Data.Bool@. Also, please excuse+-- the apparent repeated variable names. This is due to an interaction+-- between Template Haskell and Haddock.+--+----------------------------------------------------------------------------++module Data.Singletons.Bool (+ -- * The 'Bool' singleton++ Sing(SFalse, STrue),+ -- | Though Haddock doesn't show it, the 'Sing' instance above declares+ -- constructors+ --+ -- > SFalse :: Sing False+ -- > STrue :: Sing True++ SBool,+ -- | 'SBool' is a kind-restricted synonym for 'Sing': @type SBool (a :: Bool) = Sing a@++ -- * Conditionals+ If, sIf,++ -- * Singletons from @Data.Bool@+ Not, sNot, (:&&), (:||), (%:&&), (%:||),++ -- | The following are derived from the function 'bool' in @Data.Bool@. The extra+ -- underscore is to avoid name clashes with the type 'Bool'.+ Bool_, sBool_, Otherwise, sOtherwise+ ) where++import Data.Singletons+import Data.Singletons.Instances+import Data.Singletons.Singletons+import Data.Singletons.Types++#if __GLASGOW_HASKELL__ >= 707+import Data.Type.Bool++type a :&& b = a && b+type a :|| b = a || b++(%:&&) :: SBool a -> SBool b -> SBool (a :&& b)+SFalse %:&& _ = SFalse+STrue %:&& a = a++(%:||) :: SBool a -> SBool b -> SBool (a :|| b)+SFalse %:|| a = a+STrue %:|| _ = STrue++#else++$(singletonsOnly [d|+ (&&) :: Bool -> Bool -> Bool+ False && _ = False+ True && x = x++ (||) :: Bool -> Bool -> Bool+ False || x = x+ True || _ = True+ |])++#endif++sNot :: SBool a -> SBool (Not a)+sNot SFalse = STrue+sNot STrue = SFalse++-- | Conditional over singletons+sIf :: Sing a -> Sing b -> Sing c -> Sing (If a b c)+sIf STrue b _ = b+sIf SFalse _ c = c++-- ... with some functions over Booleans+$(singletonsOnly [d|+ bool_ :: a -> a -> Bool -> a+ bool_ fls _tru False = fls+ bool_ _fls tru True = tru++ otherwise :: Bool+ otherwise = True+ |])
+ src/Data/Singletons/CustomStar.hs view
@@ -0,0 +1,181 @@+{-# LANGUAGE DataKinds, TypeFamilies, KindSignatures, CPP, TemplateHaskell #-}++-----------------------------------------------------------------------------+-- |+-- Module : Data.Singletons.CustomStar+-- Copyright : (C) 2013 Richard Eisenberg+-- License : BSD-style (see LICENSE)+-- Maintainer : Richard Eisenberg (eir@cis.upenn.edu)+-- Stability : experimental+-- Portability : non-portable+--+-- This file implements 'singletonStar', which generates a datatype @Rep@ and associated+-- singleton from a list of types. The promoted version of @Rep@ is kind @*@ and the+-- Haskell types themselves. This is still very experimental, so expect unusual+-- results!+--+----------------------------------------------------------------------------++module Data.Singletons.CustomStar ( singletonStar ) where++import Language.Haskell.TH+import Language.Haskell.TH.Syntax ( Quasi(..) )+import Data.Singletons.Util+import Data.Singletons.Promote+import Data.Singletons.Singletons+import Control.Monad++#if __GLASGOW_HASKELL__ >= 707+import Data.Singletons.Decide+import Data.Singletons.Instances+import Data.Singletons.Eq+import Unsafe.Coerce+#endif++{-+The SEq instance here is tricky.+The problem is that, in GHC 7.8+, the instance of type-level (==) for *+is not recursive. Thus, it's impossible, say, to get (Maybe a == Maybe b) ~ False+from (a == b) ~ False.++There are a few ways forward:+ 1) Define SEq to use our own Boolean (==) operator, instead of the built-in one.+ This would work, but feels wrong.+ 2) Use unsafeCoerce.+We do #2.++Also to note: because these problems don't exist in GHC 7.6, the generation of+Eq and Decide for 7.6 is entirely normal.++Note that mkCustomEqInstances makes the SDecide and SEq instances in GHC 7.8+,+but the type-level (==) instance in GHC 7.6. This is perhaps poor design, but+it reduces the amount of CPP noise.+-}++-- | Produce a representation and singleton for the collection of types given.+--+-- A datatype @Rep@ is created, with one constructor per type in the declared+-- universe. When this type is promoted by the singletons library, the+-- constructors become full types in @*@, not just promoted data constructors.+--+-- For example,+--+-- > $(singletonStar [''Nat, ''Bool, ''Maybe])+--+-- generates the following:+--+-- > data Rep = Nat | Bool | Maybe Rep deriving (Eq, Show, Read)+--+-- and its singleton. However, because @Rep@ is promoted to @*@, the singleton+-- is perhaps slightly unexpected:+--+-- > data instance Sing (a :: *) where+-- > SNat :: Sing Nat+-- > SBool :: Sing Bool+-- > SMaybe :: SingRep a => Sing a -> Sing (Maybe a)+--+-- The unexpected part is that @Nat@, @Bool@, and @Maybe@ above are the real @Nat@,+-- @Bool@, and @Maybe@, not just promoted data constructors.+--+-- Please note that this function is /very/ experimental. Use at your own risk.+singletonStar :: Quasi q+ => [Name] -- ^ A list of Template Haskell @Name@s for types+ -> q [Dec]+singletonStar names = do+ kinds <- mapM getKind names+ ctors <- zipWithM (mkCtor True) names kinds+ let repDecl = DataD [] repName [] ctors+ [''Eq, ''Show, ''Read]+ fakeCtors <- zipWithM (mkCtor False) names kinds+ eqInstances <- mkCustomEqInstances fakeCtors+ singletonDecls <- singDataD True [] repName [] fakeCtors+ [''Show, ''Read+#if __GLASGOW_HASKELL__ < 707+ , ''Eq+#endif+ ]+ return $ repDecl :+ eqInstances +++ singletonDecls+ where -- get the kinds of the arguments to the tycon with the given name+ getKind :: Quasi q => Name -> q [Kind]+ getKind name = do+ info <- reifyWithWarning name+ case info of+ TyConI (DataD (_:_) _ _ _ _) ->+ fail "Cannot make a representation of a constrainted data type"+ TyConI (DataD [] _ tvbs _ _) ->+ return $ map extractTvbKind tvbs+ TyConI (NewtypeD (_:_) _ _ _ _) ->+ fail "Cannot make a representation of a constrainted newtype"+ TyConI (NewtypeD [] _ tvbs _ _) ->+ return $ map extractTvbKind tvbs+ TyConI (TySynD _ tvbs _) ->+ return $ map extractTvbKind tvbs+ PrimTyConI _ n _ ->+ return $ replicate n StarT+ _ -> fail $ "Invalid thing for representation: " ++ (show name)++ -- first parameter is whether this is a real ctor (with a fresh name)+ -- or a fake ctor (when the name is actually a Haskell type)+ mkCtor :: Quasi q => Bool -> Name -> [Kind] -> q Con+ mkCtor real name args = do+ (types, vars) <- evalForPair $ mapM kindToType args+ let ctor = NormalC ((if real then reinterpret else id) name)+ (map (\ty -> (NotStrict, ty)) types)+ if length vars > 0+ then return $ ForallC (map PlainTV vars) [] ctor+ else return ctor++ -- demote a kind back to a type, accumulating any unbound parameters+ kindToType :: Quasi q => Kind -> QWithAux [Name] q Type+ kindToType (ForallT _ _ _) = fail "Explicit forall encountered in kind"+ kindToType (AppT k1 k2) = do+ t1 <- kindToType k1+ t2 <- kindToType k2+ return $ AppT t1 t2+ kindToType (SigT _ _) = fail "Sort signature encountered in kind"+ kindToType (VarT n) = do+ addElement n+ return $ VarT n+ kindToType (ConT n) = return $ ConT n+ kindToType (PromotedT _) = fail "Promoted type used as a kind"+ kindToType (TupleT n) = return $ TupleT n+ kindToType (UnboxedTupleT _) = fail "Unboxed tuple kind encountered"+ kindToType ArrowT = return ArrowT+ kindToType ListT = return ListT+ kindToType (PromotedTupleT _) = fail "Promoted tuple kind encountered"+ kindToType PromotedNilT = fail "Promoted nil kind encountered"+ kindToType PromotedConsT = fail "Promoted cons kind encountered"+ kindToType StarT = return $ ConT repName+ kindToType ConstraintT =+ fail $ "Cannot make a representation of a type that has " +++ "an argument of kind Constraint"+ kindToType (LitT _) = fail "Literal encountered at the kind level"++mkCustomEqInstances :: Quasi q => [Con] -> q [Dec]+mkCustomEqInstances ctors = do+#if __GLASGOW_HASKELL__ >= 707+ let ctorVar = error "Internal error: Equality instance inspected ctor var"+ sCtors <- evalWithoutAux $ mapM (singCtor ctorVar) ctors+ decideInst <- mkEqualityInstance StarT sCtors sDecideClassDesc++ a <- qNewName "a"+ b <- qNewName "b"+ let eqInst = InstanceD+ []+ (AppT (ConT ''SEq) (kindParam StarT))+ [FunD '(%:==)+ [Clause [VarP a, VarP b]+ (NormalB $+ CaseE (foldExp (VarE '(%~)) [VarE a, VarE b])+ [ Match (ConP 'Proved [ConP 'Refl []])+ (NormalB $ ConE 'STrue) []+ , Match (ConP 'Disproved [WildP])+ (NormalB $ AppE (VarE 'unsafeCoerce)+ (ConE 'SFalse)) []+ ]) []]]+ return [decideInst, eqInst]+#else+ mapM mkEqTypeInstance [(c1, c2) | c1 <- ctors, c2 <- ctors]+#endif
+ src/Data/Singletons/Decide.hs view
@@ -0,0 +1,55 @@+{-# LANGUAGE CPP, RankNTypes, PolyKinds, DataKinds, TypeOperators,+ TypeFamilies, FlexibleContexts, UndecidableInstances, GADTs #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}++-----------------------------------------------------------------------------+-- |+-- Module : Data.Singletons.Decide+-- Copyright : (C) 2013 Richard Eisenberg+-- License : BSD-style (see LICENSE)+-- Maintainer : Richard Eisenberg (eir@cis.upenn.edu)+-- Stability : experimental+-- Portability : non-portable+--+-- Defines the class 'SDecide', allowing for decidable equality over singletons.+--+----------------------------------------------------------------------------++module Data.Singletons.Decide (+ -- * The SDecide class+ SDecide(..),++ -- * Supporting definitions+ (:~:)(..), Void, Refuted, Decision(..)+ ) where++import Data.Singletons+import Data.Singletons.Types+import Data.Singletons.Void++----------------------------------------------------------------------+---- SDecide ---------------------------------------------------------+----------------------------------------------------------------------++-- | Because we can never create a value of type 'Void', a function that type-checks+-- at @a -> Void@ shows that objects of type @a@ can never exist. Thus, we say that+-- @a@ is 'Refuted'+type Refuted a = (a -> Void)++-- | A 'Decision' about a type @a@ is either a proof of existence or a proof that @a@+-- cannot exist.+data Decision a = Proved a -- ^ Witness for @a@+ | Disproved (Refuted a) -- ^ Proof that no @a@ exists+ +-- | Members of the 'SDecide' "kind" class support decidable equality. Instances+-- of this class are generated alongside singleton definitions for datatypes that+-- derive an 'Eq' instance.+class (kparam ~ 'KProxy) => SDecide (kparam :: KProxy k) where+ -- | Compute a proof or disproof of equality, given two singletons.+ (%~) :: forall (a :: k) (b :: k). Sing a -> Sing b -> Decision (a :~: b)++instance SDecide ('KProxy :: KProxy k) => TestEquality (Sing :: k -> *) where+ testEquality a b =+ case a %~ b of+ Proved Refl -> Just Refl+ Disproved _ -> Nothing
+ src/Data/Singletons/Either.hs view
@@ -0,0 +1,107 @@+{-# LANGUAGE TemplateHaskell, ScopedTypeVariables, TypeFamilies, GADTs,+ DataKinds, PolyKinds, RankNTypes, UndecidableInstances, CPP #-}++#if __GLASGOW_HASKELL__ < 707+{-# OPTIONS_GHC -fno-warn-name-shadowing #-}+#endif++-----------------------------------------------------------------------------+-- |+-- Module : Data.Singletons.Either+-- Copyright : (C) 2013 Richard Eisenberg+-- License : BSD-style (see LICENSE)+-- Maintainer : Richard Eisenberg (eir@cis.upenn.edu)+-- Stability : experimental+-- Portability : non-portable+--+-- Defines functions and datatypes relating to the singleton for 'Either',+-- including a singletons version of all the definitions in @Data.Either@.+--+-- Because many of these definitions are produced by Template Haskell,+-- it is not possible to create proper Haddock documentation. Please look+-- up the corresponding operation in @Data.Either@. Also, please excuse+-- the apparent repeated variable names. This is due to an interaction+-- between Template Haskell and Haddock.+--+----------------------------------------------------------------------------++module Data.Singletons.Either (+ -- * The 'Either' singleton+ Sing(SLeft, SRight),+ -- | Though Haddock doesn't show it, the 'Sing' instance above declares+ -- constructors+ --+ -- > SLeft :: Sing a -> Sing (Left a)+ -- > SRight :: Sing b -> Sing (Right b)++ SEither,+ -- | 'SEither' is a kind-restricted synonym for 'Sing':+ -- @type SEither (a :: Either x y) = Sing a@++ -- * Singletons from @Data.Either@+ Either_, sEither_,+ -- | The preceding two definitions are derived from the function 'either' in+ -- @Data.Either@. The extra underscore is to avoid name clashes with the type+ -- 'Either'.++ Lefts, sLefts, Rights, sRights,+ PartitionEithers, sPartitionEithers, IsLeft, sIsLeft, IsRight, sIsRight+ ) where++import Data.Singletons.Instances+import Data.Singletons.TH+import Data.Singletons.List++$(singletonsOnly [d|+ -- | Case analysis for the 'Either' type.+ -- If the value is @'Left' a@, apply the first function to @a@;+ -- if it is @'Right' b@, apply the second function to @b@.+ either_ :: (a -> c) -> (b -> c) -> Either a b -> c+ either_ f _ (Left x) = f x+ either_ _ g (Right y) = g y++ -- | Extracts from a list of 'Either' all the 'Left' elements+ -- All the 'Left' elements are extracted in order.++ lefts :: [Either a b] -> [a]+ lefts [] = []+ lefts (Left x : xs) = x : lefts xs+ lefts (Right _ : xs) = lefts xs++ -- | Extracts from a list of 'Either' all the 'Right' elements+ -- All the 'Right' elements are extracted in order.++ rights :: [Either a b] -> [b]+ rights [] = []+ rights (Left _ : xs) = rights xs+ rights (Right x : xs) = x : rights xs++ -- | Partitions a list of 'Either' into two lists+ -- All the 'Left' elements are extracted, in order, to the first+ -- component of the output. Similarly the 'Right' elements are extracted+ -- to the second component of the output.++ partitionEithers :: [Either a b] -> ([a],[b])+ partitionEithers es = partitionEithers_aux ([], []) es++ partitionEithers_aux :: ([a],[b]) -> [Either a b] -> ([a],[b])+ partitionEithers_aux (as,bs) [] = (reverse as,reverse bs)+ partitionEithers_aux (as,bs) (Left a : es) =+ partitionEithers_aux (a : as, bs) es+ partitionEithers_aux (as,bs) (Right b : es) =+ partitionEithers_aux (as, b : bs) es++ -- | Return `True` if the given value is a `Left`-value, `False` otherwise.+ --+ -- /Since: 4.7.0.0/+ isLeft :: Either a b -> Bool+ isLeft (Left _) = True+ isLeft (Right _) = False++ -- | Return `True` if the given value is a `Right`-value, `False` otherwise.+ --+ -- /Since: 4.7.0.0/+ isRight :: Either a b -> Bool+ isRight (Left _) = False+ isRight (Right _) = True+ |])
+ src/Data/Singletons/Eq.hs view
@@ -0,0 +1,51 @@+{-# LANGUAGE TypeOperators, DataKinds, PolyKinds, TypeFamilies,+ RankNTypes, FlexibleContexts, TemplateHaskell,+ UndecidableInstances, GADTs, CPP #-}++-----------------------------------------------------------------------------+-- |+-- Module : Data.Singletons.Eq+-- Copyright : (C) 2013 Richard Eisenberg+-- License : BSD-style (see LICENSE)+-- Maintainer : Richard Eisenberg (eir@cis.upenn.edu)+-- Stability : experimental+-- Portability : non-portable+--+-- Defines the SEq singleton version of the Eq type class.+--+-----------------------------------------------------------------------------++module Data.Singletons.Eq (+ SEq(..),+ type (==), (:==), (:/=)+ ) where++import Data.Singletons.Util+import Data.Singletons.Bool+import Data.Singletons+import Data.Singletons.Singletons+import Data.Singletons.Instances+import Data.Singletons.Types+#if __GLASGOW_HASKELL__ < 707+import Data.Singletons.Promote ( promoteEqInstances )+#endif++-- | A type synonym conforming to singletons naming conventions+type a :/= b = Not (a :== b)+ +-- | The singleton analogue of 'Eq'. Unlike the definition for 'Eq', it is required+-- that instances define a body for '(%:==)'. You may also supply a body for '(%:/=)'.+class (kparam ~ 'KProxy) => SEq (kparam :: KProxy k) where+ -- | Boolean equality on singletons+ (%:==) :: forall (a :: k) (b :: k). Sing a -> Sing b -> Sing (a :== b)++ -- | Boolean disequality on singletons+ (%:/=) :: forall (a :: k) (b :: k). Sing a -> Sing b -> Sing (a :/= b)+ a %:/= b = sNot (a %:== b)+++#if __GLASGOW_HASKELL__ < 707+$(promoteEqInstances basicTypes) -- these instances are in Data.Type.Equality+#endif++$(singEqInstancesOnly basicTypes)
+ src/Data/Singletons/Instances.hs view
@@ -0,0 +1,29 @@+{- Data/Singletons/Instances.hs++(c) Richard Eisenberg 2013+eir@cis.upenn.edu++This (internal) module contains the main class definitions for singletons,+re-exported from various places.++-}++{-# LANGUAGE CPP, RankNTypes, DataKinds, PolyKinds, GADTs, TypeFamilies,+ FlexibleContexts, TemplateHaskell, ScopedTypeVariables,+ UndecidableInstances, TypeOperators, FlexibleInstances #-}+#if __GLASGOW_HASKELL__ < 707+ -- optimizing instances of SDecide cause GHC to die (#8467)+{-# OPTIONS_GHC -O0 #-}+#endif++{-# OPTIONS_GHC -fno-warn-orphans #-}++module Data.Singletons.Instances where++import Data.Singletons.Singletons+import Data.Singletons.Util++-- some useful singletons+$(genSingletons basicTypes)+$(singDecideInstances basicTypes)+
+ src/Data/Singletons/List.hs view
@@ -0,0 +1,69 @@+{-# LANGUAGE CPP, TypeOperators, DataKinds, PolyKinds, TypeFamilies,+ TemplateHaskell, GADTs, UndecidableInstances #-}++#if __GLASGOW_HASKELL__ < 707+{-# OPTIONS_GHC -fno-warn-name-shadowing #-}+#endif++-----------------------------------------------------------------------------+-- |+-- Module : Data.Singletons.List+-- Copyright : (C) 2013 Richard Eisenberg+-- License : BSD-style (see LICENSE)+-- Maintainer : Richard Eisenberg (eir@cis.upenn.edu)+-- Stability : experimental+-- Portability : non-portable+--+-- Defines functions and datatypes relating to the singleton for '[]',+-- including a singletons version of a few of the definitions in @Data.List@.+--+-- Because many of these definitions are produced by Template Haskell,+-- it is not possible to create proper Haddock documentation. Please look+-- up the corresponding operation in @Data.List@. Also, please excuse+-- the apparent repeated variable names. This is due to an interaction+-- between Template Haskell and Haddock.+--+----------------------------------------------------------------------------++module Data.Singletons.List (+ -- * The singleton for lists+ Sing(SNil, SCons),+ -- | Though Haddock doesn't show it, the 'Sing' instance above declares+ -- constructors+ --+ -- > SNil :: Sing '[]+ -- > SCons :: Sing (h :: k) -> Sing (t :: [k]) -> Sing (h ': t)++ SList,+ -- | 'SList' is a kind-restricted synonym for 'Sing': @type SList (a :: [k]) = Sing a@++ Head, Tail, sHead, sTail,+ (:++), (%:++),+ Reverse, sReverse+ ) where++import Data.Singletons.Instances+import Data.Singletons+import Data.Singletons.Singletons+import Data.Singletons.TypeLits++$(singletonsOnly [d|+ (++) :: [a] -> [a] -> [a]+ [] ++ a = a+ (h:t) ++ a = h:(t ++ a)++ head :: [a] -> a+ head (a : _) = a+ head [] = error "Data.Singletons.List.head: empty list"++ tail :: [a] -> [a]+ tail (_ : t) = t+ tail [] = error "Data.Singletons.List.tail: empty list"++ reverse :: [a] -> [a]+ reverse list = reverse_aux [] list++ reverse_aux :: [a] -> [a] -> [a]+ reverse_aux acc [] = acc+ reverse_aux acc (h : t) = reverse_aux (h : acc) t+ |])
+ src/Data/Singletons/Maybe.hs view
@@ -0,0 +1,121 @@+{-# LANGUAGE TemplateHaskell, ScopedTypeVariables, TypeFamilies,+ DataKinds, PolyKinds, UndecidableInstances, GADTs,+ RankNTypes, CPP #-}++#if __GLASGOW_HASKELL__ < 707+{-# OPTIONS_GHC -fno-warn-name-shadowing #-}+#endif++-----------------------------------------------------------------------------+-- |+-- Module : Data.Singletons.Maybe+-- Copyright : (C) 2013 Richard Eisenberg+-- License : BSD-style (see LICENSE)+-- Maintainer : Richard Eisenberg (eir@cis.upenn.edu)+-- Stability : experimental+-- Portability : non-portable+--+-- Defines functions and datatypes relating to the singleton for 'Maybe',+-- including a singletons version of all the definitions in @Data.Maybe@.+--+-- Because many of these definitions are produced by Template Haskell,+-- it is not possible to create proper Haddock documentation. Please look+-- up the corresponding operation in @Data.Maybe@. Also, please excuse+-- the apparent repeated variable names. This is due to an interaction+-- between Template Haskell and Haddock.+--+----------------------------------------------------------------------------+++module Data.Singletons.Maybe (+ -- The 'Maybe' singleton++ Sing(SNothing, SJust),+ -- | Though Haddock doesn't show it, the 'Sing' instance above declares+ -- constructors+ --+ -- > SNothing :: Sing Nothing+ -- > SJust :: Sing a -> Sing (Just a)++ SMaybe,+ -- | 'SBool' is a kind-restricted synonym for 'Sing': @type SMaybe (a :: Maybe k) = Sing a@++ -- * Singletons from @Data.Maybe@++ Maybe_, sMaybe_,+ -- | The preceding two definitions are derived from the function 'maybe' in+ -- @Data.Maybe@. The extra underscore is to avoid name clashes with the type+ -- 'Maybe'.++ IsJust, sIsJust, IsNothing, sIsNothing,+ FromJust, sFromJust, FromMaybe, sFromMaybe, MaybeToList, sMaybeToList,+ ListToMaybe, sListToMaybe, CatMaybes, sCatMaybes, MapMaybe, sMapMaybe+ ) where++import Data.Singletons.Instances+import Data.Singletons+import Data.Singletons.TH+import Data.Singletons.List+import Data.Singletons.TypeLits++$(singletonsOnly [d|+ -- | The 'maybe' function takes a default value, a function, and a 'Maybe'+ -- value. If the 'Maybe' value is 'Nothing', the function returns the+ -- default value. Otherwise, it applies the function to the value inside+ -- the 'Just' and returns the result.+ maybe_ :: b -> (a -> b) -> Maybe a -> b+ maybe_ n _ Nothing = n+ maybe_ _ f (Just x) = f x++ -- | The 'isJust' function returns 'True' iff its argument is of the+ -- form @Just _@.+ isJust :: Maybe a -> Bool+ isJust Nothing = False+ isJust (Just _) = True++ -- | The 'isNothing' function returns 'True' iff its argument is 'Nothing'.+ isNothing :: Maybe a -> Bool+ isNothing Nothing = True+ isNothing (Just _) = False++ -- | The 'fromJust' function extracts the element out of a 'Just' and+ -- throws an error if its argument is 'Nothing'.+ fromJust :: Maybe a -> a+ fromJust Nothing = error "Maybe.fromJust: Nothing" -- yuck+ fromJust (Just x) = x++ -- | The 'fromMaybe' function takes a default value and and 'Maybe'+ -- value. If the 'Maybe' is 'Nothing', it returns the default values;+ -- otherwise, it returns the value contained in the 'Maybe'.+ fromMaybe :: a -> Maybe a -> a+ fromMaybe d Nothing = d+ fromMaybe _ (Just v) = v++ -- | The 'maybeToList' function returns an empty list when given+ -- 'Nothing' or a singleton list when not given 'Nothing'.+ maybeToList :: Maybe a -> [a]+ maybeToList Nothing = []+ maybeToList (Just x) = [x]++ -- | The 'listToMaybe' function returns 'Nothing' on an empty list+ -- or @'Just' a@ where @a@ is the first element of the list.+ listToMaybe :: [a] -> Maybe a+ listToMaybe [] = Nothing+ listToMaybe (a:_) = Just a++ -- | The 'catMaybes' function takes a list of 'Maybe's and returns+ -- a list of all the 'Just' values.+ catMaybes :: [Maybe a] -> [a]+ catMaybes [] = []+ catMaybes (Just x : xs) = x : catMaybes xs+ catMaybes (Nothing : xs) = catMaybes xs++ -- | The 'mapMaybe' function is a version of 'map' which can throw+ -- out elements. In particular, the functional argument returns+ -- something of type @'Maybe' b@. If this is 'Nothing', no element+ -- is added on to the result list. If it just @'Just' b@, then @b@ is+ -- included in the result list.+ mapMaybe :: (a -> Maybe b) -> [a] -> [b]+ mapMaybe _ [] = []+ mapMaybe f (x:xs) = maybeToList (f x) ++ (mapMaybe f xs)+ |])
+ src/Data/Singletons/Prelude.hs view
@@ -0,0 +1,106 @@+-----------------------------------------------------------------------------+-- |+-- Module : Data.Singletons.Prelude+-- Copyright : (C) 2013 Richard Eisenberg+-- License : BSD-style (see LICENSE)+-- Maintainer : Richard Eisenberg (eir@cis.upenn.edu)+-- Stability : experimental+-- Portability : non-portable+--+-- Mimics the Haskell Prelude, but with singleton types. Includes the basic+-- singleton definitions. Note: This is currently very incomplete!+--+-- Because many of these definitions are produced by Template Haskell, it is+-- not possible to create proper Haddock documentation. Also, please excuse+-- the apparent repeated variable names. This is due to an interaction between+-- Template Haskell and Haddock.+--+----------------------------------------------------------------------------++module Data.Singletons.Prelude (+ -- * Basic singleton definitions+ module Data.Singletons,++ Sing(SFalse, STrue, SNil, SCons, SJust, SNothing, SLeft, SRight, SLT, SEQ, SGT,+ STuple0, STuple2, STuple3, STuple4, STuple5, STuple6, STuple7),+ -- | Though Haddock doesn't show it, the 'Sing' instance above includes+ -- the following instances+ --+ -- > data instance Sing (a :: Bool) where+ -- > SFalse :: Sing False+ -- > STrue :: Sing True+ -- >+ -- > data instance Sing (a :: [k]) where+ -- > SNil :: Sing '[]+ -- > SCons :: Sing (h :: k) -> Sing (t :: [k]) -> Sing (h ': t)+ -- >+ -- > data instance Sing (a :: Maybe k) where+ -- > SNothing :: Sing Nothing+ -- > SJust :: Sing (a :: k) -> Sing (Just a)+ -- >+ -- > data instance Sing (a :: Either x y) where+ -- > SLeft :: Sing (a :: x) -> Sing (Left a)+ -- > SRight :: Sing (b :: y) -> Sing (Right b)+ -- >+ -- > data instance Sing (a :: Ordering) where+ -- > SLT :: Sing LT+ -- > SEQ :: Sing EQ+ -- > SGT :: Sing GT+ -- >+ -- > data instance Sing (a :: ()) where+ -- > STuple0 :: Sing '()+ -- >+ -- > data instance Sing (z :: (a, b)) where+ -- > STuple2 :: Sing a -> Sing b -> Sing '(a, b)+ -- >+ -- > data instance Sing (z :: (a, b, c)) where+ -- > STuple3 :: Sing a -> Sing b -> Sing c -> Sing '(a, b, c)+ -- >+ -- > data instance Sing (z :: (a, b, c, d)) where+ -- > STuple4 :: Sing a -> Sing b -> Sing c -> Sing d -> Sing '(a, b, c, d)+ -- >+ -- > data instance Sing (z :: (a, b, c, d, e)) where+ -- > STuple5 :: Sing a -> Sing b -> Sing c -> Sing d -> Sing e -> Sing '(a, b, c, d, e)+ -- >+ -- > data instance Sing (z :: (a, b, c, d, e, f)) where+ -- > STuple6 :: Sing a -> Sing b -> Sing c -> Sing d -> Sing e -> Sing f+ -- > -> Sing '(a, b, c, d, e, f)+ -- >+ -- > data instance Sing (z :: (a, b, c, d, e, f, g)) where+ -- > STuple7 :: Sing a -> Sing b -> Sing c -> Sing d -> Sing e -> Sing f+ -- > -> Sing g -> Sing '(a, b, c, d, e, f, g)++ -- * Singleton type synonyms++ -- | These synonyms are all kind-restricted synonyms of 'Sing'.+ -- For example 'SBool' requires an argument of kind 'Bool'.+ SBool, SList, SMaybe, SEither, SOrdering,+ STuple0, STuple2, STuple3, STuple4, STuple5, STuple6, STuple7,++ -- * Functions working with 'Bool'+ If, sIf, Not, sNot, (:&&), (:||), (%:&&), (%:||),++ -- * Functions working with lists+ Head, Tail, (:++), (%:++),++ -- * Error reporting+ Error, sError,++ -- * Singleton equality+ module Data.Singletons.Eq,++ -- * Other datatypes+ Maybe_, sMaybe_,+ Either_, sEither_,+ Fst, sFst, Snd, sSnd, Curry, sCurry, Uncurry, sUncurry+ ) where++import Data.Singletons+import Data.Singletons.Bool+import Data.Singletons.List+import Data.Singletons.Maybe+import Data.Singletons.Either+import Data.Singletons.Tuple+import Data.Singletons.Eq+import Data.Singletons.Instances+import Data.Singletons.TypeLits
+ src/Data/Singletons/Promote.hs view
@@ -0,0 +1,699 @@+{- Data/Singletons/Promote.hs++(c) Richard Eisenberg 2013+eir@cis.upenn.edu++This file contains functions to promote term-level constructs to the+type level. It is an internal module to the singletons package.+-}++{-# LANGUAGE TemplateHaskell, CPP #-}++module Data.Singletons.Promote where++import Language.Haskell.TH hiding ( Q, cxt )+import Language.Haskell.TH.Syntax ( falseName, trueName, Quasi(..) )+import Data.Singletons.Util+import Data.Singletons.Types+import GHC.Exts (Any)+import GHC.TypeLits (Symbol)+import Prelude hiding (exp)+import qualified Data.Map as Map+import qualified Data.Set as Set+import Control.Monad+import Data.List++anyTypeName, boolName, andName, tyEqName, repName, ifName,+ headName, tailName, symbolName :: Name+anyTypeName = ''Any+boolName = ''Bool+andName = '(&&)+#if __GLASGOW_HASKELL__ >= 707+tyEqName = ''(==)+#else+tyEqName = ''(:==)+#endif+repName = mkName "Rep"+ifName = ''If+headName = mkName "Head" -- these will go away with the th-desugar change+tailName = mkName "Tail"+symbolName = ''Symbol++falseTy :: Type+falseTy = PromotedT falseName++trueTy :: Type+trueTy = PromotedT trueName++boolTy :: Type+boolTy = ConT boolName++andTy :: Type+andTy = promoteVal andName++ifTyFam :: Type+ifTyFam = ConT ifName++headTyFam :: Type+headTyFam = ConT headName++tailTyFam :: Type+tailTyFam = ConT tailName++promoteInfo :: Quasi q => Info -> q [Dec]+promoteInfo (ClassI _dec _instances) =+ fail "Promotion of class info not supported"+promoteInfo (ClassOpI _name _ty _className _fixity) =+ fail "Promotion of class members info not supported"+promoteInfo (TyConI dec) = evalWithoutAux $ promoteDec Map.empty dec+promoteInfo (FamilyI _dec _instances) =+ fail "Promotion of type family info not yet supported" -- KindFams+promoteInfo (PrimTyConI _name _numArgs _unlifted) =+ fail "Promotion of primitive type constructors not supported"+promoteInfo (DataConI _name _ty _tyname _fixity) =+ fail $ "Promotion of individual constructors not supported; " +++ "promote the type instead"+promoteInfo (VarI _name _ty _mdec _fixity) =+ fail "Promotion of value info not supported"+promoteInfo (TyVarI _name _ty) =+ fail "Promotion of type variable info not supported"++promoteValName :: Name -> Name+promoteValName n+ | nameBase n == "undefined" = anyTypeName+ | otherwise = upcase n++promoteVal :: Name -> Type+promoteVal = ConT . promoteValName++promoteType :: Quasi q => Type -> q Kind+-- We don't need to worry about constraints: they are used to express+-- static guarantees at runtime. But, because we don't need to do+-- anything special to keep static guarantees at compile time, we don't+-- need to promote them.+promoteType (ForallT _tvbs _ ty) = promoteType ty -- ForallKinds+promoteType (VarT name) = return $ VarT name+promoteType (ConT name) = return $+ case nameBase name of+ "TypeRep" -> StarT+ "String" -> ConT symbolName+ x | x == nameBase repName -> StarT+ | otherwise -> ConT name+promoteType (TupleT n) = return $ TupleT n+promoteType (UnboxedTupleT _n) = fail "Promotion of unboxed tuples not supported"+promoteType ArrowT = return ArrowT+promoteType ListT = return ListT+promoteType (AppT (AppT ArrowT (ForallT (_:_) _ _)) _) =+ fail "Cannot promote types of rank above 1."+promoteType (AppT ty1 ty2) = do+ k1 <- promoteType ty1+ k2 <- promoteType ty2+ return $ AppT k1 k2+promoteType (SigT _ty _) = fail "Cannot promote type of kind other than *"+promoteType (LitT _) = fail "Cannot promote a type-level literal"+promoteType (PromotedT _) = fail "Cannot promote a promoted data constructor"+promoteType (PromotedTupleT _) = fail "Cannot promote tuples that are already promoted"+promoteType PromotedNilT = fail "Cannot promote a nil that is already promoted"+promoteType PromotedConsT = fail "Cannot promote a cons that is already promoted"+promoteType StarT = fail "* used as a type"+promoteType ConstraintT = fail "Constraint used as a type"++-- a table to keep track of variable->type mappings+type TypeTable = Map.Map Name Type++-- | Promote every declaration given to the type level, retaining the originals.+promote :: Quasi q => q [Dec] -> q [Dec]+promote qdec = do+ decls <- qdec+ promDecls <- promoteDecs decls+ return $ decls ++ promDecls++-- | Promote each declaration, discarding the originals.+promoteOnly :: Quasi q => q [Dec] -> q [Dec]+promoteOnly qdec = do+ decls <- qdec+ promDecls <- promoteDecs decls+ return promDecls++checkForRep :: Quasi q => [Name] -> q ()+checkForRep names =+ when (any ((== nameBase repName) . nameBase) names)+ (fail $ "A data type named <<Rep>> is a special case.\n" +++ "Promoting it will not work as expected.\n" +++ "Please choose another name for your data type.")++checkForRepInDecls :: Quasi q => [Dec] -> q ()+checkForRepInDecls decls =+ checkForRep (map extractNameFromDec decls)+ where extractNameFromDec :: Dec -> Name+ extractNameFromDec (DataD _ name _ _ _) = name+ extractNameFromDec (NewtypeD _ name _ _ _) = name+ extractNameFromDec (TySynD name _ _) = name+ extractNameFromDec (FamilyD _ name _ _) = name+ extractNameFromDec _ = mkName "NotRep"++-- Note [Promoting declarations in two stages]+-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+--+-- Promoting declarations proceeds in two stages:+-- 1) Promote everything except type signatures+-- 2) Promote type signatures. This must be done in a second pass+-- because a function type signature gets promoted to a type family+-- declaration. Although function signatures do not differentiate+-- between uniform parameters and non-uniform parameters, type+-- family declarations do. We need to process a function's+-- definition to get the count of non-uniform parameters before+-- producing the type family declaration. At this point, any+-- function written without a type signature is rejected and+-- removed.+--+-- Consider this example:+--+-- foo :: Int -> Bool -> Bool+-- foo 0 = id+-- foo _ = not+--+-- Here the first parameter to foo is non-uniform, because it is+-- inspected in a pattern and can be different in each defining+-- equation of foo. The second parameter to foo, specified in the type+-- signature as Bool, is a uniform parameter - it is not inspected and+-- each defining equation of foo uses it the same way. The foo+-- function will be promoted to a type familty Foo like this:+--+-- type family Foo (n :: Int) :: Bool -> Bool where+-- Foo 0 = Id+-- Foo a = Not+--+-- To generate type signature for Foo type family we must first learn+-- what is the actual number of patterns used in defining cequations+-- of foo. In this case there is only one so we declare Foo to take+-- one argument and have return type of Bool -> Bool.++-- Promote a list of declarations.+promoteDecs :: Quasi q => [Dec] -> q [Dec]+promoteDecs decls = do+ checkForRepInDecls decls+ let vartbl = Map.empty+ -- See Note [Promoting declarations in two stages]+ (newDecls, table) <- evalForPair $ mapM (promoteDec vartbl) decls+ (declss, namess) <- mapAndUnzipM (promoteDec' table) decls+ let moreNewDecls = concat declss+ names = concat namess+ noTypeSigs = Set.toList $ Set.difference (Map.keysSet $+#if __GLASGOW_HASKELL__ >= 707+ Map.filter ((>= 0) . fst) table)+#else+ Map.filter (>= 0) table)+#endif+ (Set.fromList names)+ when (not . null $ noTypeSigs) $ fail ("No type signature for functions: "+ ++ intercalate ", " (map (show . nameBase) noTypeSigs)+ ++ "; cannot promote or make singletons.") + return (concat newDecls ++ moreNewDecls)++-- | Produce instances for '(:==)' (type-level equality) from the given types+promoteEqInstances :: Quasi q => [Name] -> q [Dec]+promoteEqInstances = concatMapM promoteEqInstance++-- | Produce an instance for '(:==)' (type-level equality) from the given type+promoteEqInstance :: Quasi q => Name -> q [Dec]+promoteEqInstance name = do+ (_tvbs, cons) <- getDataD "I cannot make an instance of (:==:) for it." name+#if __GLASGOW_HASKELL__ >= 707+ vars <- replicateM (length _tvbs) (qNewName "k")+ let tyvars = map VarT vars+ kind = foldType (ConT name) tyvars+ inst_decs <- mkEqTypeInstance kind cons+ return inst_decs+#else+ let pairs = [(c1, c2) | c1 <- cons, c2 <- cons]+ mapM mkEqTypeInstance pairs+#endif++#if __GLASGOW_HASKELL__ >= 707++-- produce a closed type family helper and the instance+-- for (:==) over the given list of ctors+mkEqTypeInstance :: Quasi q => Kind -> [Con] -> q [Dec]+mkEqTypeInstance kind cons = do+ helperName <- newUniqueName "Equals"+ aName <- qNewName "a"+ bName <- qNewName "b"+ true_branches <- mapM mk_branch cons+ false_branch <- false_case+ let closedFam = ClosedTypeFamilyD helperName+ [ KindedTV aName kind+ , KindedTV bName kind ]+ (Just boolTy)+ (true_branches ++ [false_branch])+ eqInst = TySynInstD tyEqName (TySynEqn [ SigT (VarT aName) kind+ , SigT (VarT bName) kind ]+ (foldType (ConT helperName)+ [VarT aName, VarT bName]))+ return [closedFam, eqInst]++ where mk_branch :: Quasi q => Con -> q TySynEqn+ mk_branch con = do+ let (name, numArgs) = extractNameArgs con+ lnames <- replicateM numArgs (qNewName "a")+ rnames <- replicateM numArgs (qNewName "b")+ let lvars = map VarT lnames+ rvars = map VarT rnames+ ltype = foldType (PromotedT name) lvars+ rtype = foldType (PromotedT name) rvars+ results = zipWith (\l r -> foldType (ConT tyEqName) [l, r]) lvars rvars+ result = tyAll results+ return $ TySynEqn [ltype, rtype] result++ false_case :: Quasi q => q TySynEqn+ false_case = do+ lvar <- qNewName "a"+ rvar <- qNewName "b"+ return $ TySynEqn [SigT (VarT lvar) kind, SigT (VarT rvar) kind] falseTy++ tyAll :: [Type] -> Type -- "all" at the type level+ tyAll [] = trueTy+ tyAll [one] = one+ tyAll (h:t) = foldType andTy [h, (tyAll t)]++#else++-- produce the type instance for (:==) for the given pair of constructors+mkEqTypeInstance :: Quasi q => (Con, Con) -> q Dec+mkEqTypeInstance (c1, c2) =+ if c1 == c2+ then do+ let (name, numArgs) = extractNameArgs c1+ lnames <- replicateM numArgs (qNewName "a")+ rnames <- replicateM numArgs (qNewName "b")+ let lvars = map VarT lnames+ rvars = map VarT rnames+ return $ TySynInstD+ tyEqName+ [foldType (PromotedT name) lvars,+ foldType (PromotedT name) rvars]+ (tyAll (zipWith (\l r -> foldType (ConT tyEqName) [l, r])+ lvars rvars))+ else do+ let (lname, lNumArgs) = extractNameArgs c1+ (rname, rNumArgs) = extractNameArgs c2+ lnames <- replicateM lNumArgs (qNewName "a")+ rnames <- replicateM rNumArgs (qNewName "b")+ return $ TySynInstD+ tyEqName+ [foldType (PromotedT lname) (map VarT lnames),+ foldType (PromotedT rname) (map VarT rnames)]+ falseTy+ where tyAll :: [Type] -> Type -- "all" at the type level+ tyAll [] = trueTy+ tyAll [one] = one+ tyAll (h:t) = foldType andTy [h, (tyAll t)]++#endif++-- keeps track of the number of non-uniform parameters to promoted values+-- and all of the instance equations for those values+#if __GLASGOW_HASKELL__ >= 707+type PromoteTable = Map.Map Name (Int, [TySynEqn])+#else+type PromoteTable = Map.Map Name Int+#endif+type PromoteQ q = QWithAux PromoteTable q++-- used when a type is declared as a type synonym, not a type family+-- no need to declare "type family ..." for these+typeSynonymFlag :: Int+typeSynonymFlag = -1++promoteDec :: Quasi q => TypeTable -> Dec -> PromoteQ q [Dec]+promoteDec vars (FunD name clauses) = do+ let proName = promoteValName name+ vars' = Map.insert name (promoteVal name) vars+ numArgs = getNumPats (head clauses) -- count the parameters+ -- Haskell requires all clauses to have the same number of parameters+ (eqns, instDecls) <- evalForPair $+ mapM (promoteClause vars' proName) clauses+#if __GLASGOW_HASKELL__ >= 707+ addBinding name (numArgs, eqns) -- remember the number of parameters and the eqns+ return instDecls+#else+ addBinding name numArgs -- remember the number of parameters+ return $ eqns ++ instDecls+#endif+ where getNumPats :: Clause -> Int+ getNumPats (Clause pats _ _) = length pats+promoteDec vars (ValD pat body decs) = do+ -- see also the comment for promoteTopLevelPat+ when (length decs > 0)+ (fail $ "Promotion of global variable with <<where>> clause " +++ "not yet supported")+ (rhs, decls) <- evalForPair $ promoteBody vars body+ (lhss, decls') <- evalForPair $ promoteTopLevelPat pat+ -- just use "type" decls+#if __GLASGOW_HASKELL__ >= 707+ mapM_ (flip addBinding (typeSynonymFlag, [])) (map lhsRawName lhss)+#else+ mapM_ (flip addBinding typeSynonymFlag) (map lhsRawName lhss)+#endif+ return $ (map (\(LHS _ nm hole) -> TySynD nm [] (hole rhs)) lhss) +++ decls ++ decls'+promoteDec vars (DataD cxt name tvbs ctors derivings) =+ promoteDataD vars cxt name tvbs ctors derivings+promoteDec vars (NewtypeD cxt name tvbs ctor derivings) =+ promoteDataD vars cxt name tvbs [ctor] derivings+promoteDec _vars (TySynD _name _tvbs _ty) =+ fail "Promotion of type synonym declaration not yet supported"+promoteDec _vars (ClassD _cxt _name _tvbs _fundeps _decs) =+ fail "Promotion of class declaration not yet supported"+promoteDec _vars (InstanceD _cxt _ty _decs) =+ fail "Promotion of instance declaration not yet supported"+promoteDec _vars (SigD _name _ty) = return [] -- handle in promoteDec'+promoteDec _vars (ForeignD _fgn) =+ fail "Promotion of foreign function declaration not yet supported"+promoteDec _vars (InfixD fixity name)+ | isUpcase name = return [] -- automatic: promoting a type or data ctor+ | otherwise = return [InfixD fixity (promoteValName name)] -- value+promoteDec _vars (PragmaD _prag) =+ fail "Promotion of pragmas not yet supported"+promoteDec _vars (FamilyD _flavour _name _tvbs _mkind) =+ fail "Promotion of type and data families not yet supported"+promoteDec _vars (DataInstD _cxt _name _tys _ctors _derivings) =+ fail "Promotion of data instances not yet supported"+promoteDec _vars (NewtypeInstD _cxt _name _tys _ctors _derivings) =+ fail "Promotion of newtype instances not yet supported"+#if __GLASGOW_HASKELL__ >= 707+promoteDec _vars (RoleAnnotD _name _roles) =+ return [] -- silently ignore role annotations, as they're harmless here+promoteDec _vars (ClosedTypeFamilyD _name _tvs _mkind _eqns) =+ fail "Promotion of closed type families not yet supported"+promoteDec _vars (TySynInstD _name _eqn) =+#else+promoteDec _vars (TySynInstD _name _lhs _rhs) =+#endif+ fail "Promotion of type synonym instances not yet supported"++-- only need to check if the datatype derives Eq. The rest is automatic.+promoteDataD :: Quasi q => TypeTable -> Cxt -> Name -> [TyVarBndr] -> [Con] ->+ [Name] -> PromoteQ q [Dec]+promoteDataD _vars _cxt _name _tvbs ctors derivings =+ if any (\n -> (nameBase n) == "Eq") derivings+ then do+#if __GLASGOW_HASKELL__ >= 707+ kvs <- replicateM (length _tvbs) (qNewName "k")+ inst_decs <- mkEqTypeInstance (foldType (ConT _name) (map VarT kvs)) ctors+ return inst_decs+#else+ let pairs = [ (c1, c2) | c1 <- ctors, c2 <- ctors ]+ mapM mkEqTypeInstance pairs+#endif+ else return [] -- the actual promotion is automatic++-- second pass through declarations to deal with type signatures+-- returns the new declarations and the list of names that have been+-- processed+promoteDec' :: Quasi q => PromoteTable -> Dec -> q ([Dec], [Name])+promoteDec' tab (SigD name ty) = case Map.lookup name tab of+ Nothing -> fail $ "Type declaration is missing its binding: " ++ (show name)+#if __GLASGOW_HASKELL__ >= 707+ Just (numArgs, eqns) ->+#else+ Just numArgs ->+#endif+ -- if there are no args, then use a type synonym, not a type family+ -- in the type synonym case, we ignore the type signature+ if numArgs == typeSynonymFlag then return $ ([], [name]) else do+ k <- promoteType ty+ let ks = unravel k+ (argKs, resultKs) = splitAt numArgs ks -- divide by uniformity+ resultK <- ravel resultKs -- rebuild the arrow kind+ tyvarNames <- mapM qNewName (replicate (length argKs) "a")+#if __GLASGOW_HASKELL__ >= 707+ return ([ClosedTypeFamilyD (promoteValName name)+ (zipWith KindedTV tyvarNames argKs)+ (Just resultK)+ eqns], [name])+#else+ return ([FamilyD TypeFam+ (promoteValName name)+ (zipWith KindedTV tyvarNames argKs)+ (Just resultK)], [name])+#endif+ where unravel :: Kind -> [Kind] -- get argument kinds from an arrow kind+ unravel (AppT (AppT ArrowT k1) k2) =+ let ks = unravel k2 in k1 : ks+ unravel k = [k]++ ravel :: Quasi q => [Kind] -> q Kind+ ravel [] = fail "Internal error: raveling nil"+ ravel [k] = return k+ ravel (h:t) = do+ k <- ravel t+ return $ (AppT (AppT ArrowT h) k)+promoteDec' _ _ = return ([], [])++#if __GLASGOW_HASKELL__ >= 707+promoteClause :: Quasi q => TypeTable -> Name -> Clause -> QWithDecs q TySynEqn+#else+promoteClause :: Quasi q => TypeTable -> Name -> Clause -> QWithDecs q Dec+#endif+promoteClause vars _name (Clause pats body []) = do+ -- promoting the patterns creates variable bindings. These are passed+ -- to the function promoted the RHS+ (types, vartbl) <- evalForPair $ mapM promotePat pats+ let vars' = Map.union vars vartbl+ ty <- promoteBody vars' body+#if __GLASGOW_HASKELL__ >= 707+ return $ TySynEqn types ty+#else+ return $ TySynInstD _name types ty+#endif+promoteClause _ _ (Clause _ _ (_:_)) =+ fail "A <<where>> clause in a function definition is not yet supported"++-- the LHS of a top-level expression is a name and "type with hole"+-- the hole is filled in by the RHS+data TopLevelLHS = LHS { lhsRawName :: Name -- the unpromoted name+ , lhsName :: Name+ , lhsHole :: Type -> Type+ }++-- Treatment of top-level patterns is different from other patterns+-- because type families have type patterns as their LHS. However,+-- it is not possible to use type patterns at the top level, so we+-- have to use other techniques.+promoteTopLevelPat :: Quasi q => Pat -> QWithDecs q [TopLevelLHS]+promoteTopLevelPat (LitP _) = fail "Cannot declare a global literal."+promoteTopLevelPat (VarP name) = return [LHS name (promoteValName name) id]+promoteTopLevelPat (TupP pats) = case length pats of+ 0 -> return [] -- unit as LHS of pattern... ignore+ 1 -> fail "1-tuple encountered during top-level pattern promotion"+ n -> promoteTopLevelPat (ConP (tupleDataName n) pats)+promoteTopLevelPat (UnboxedTupP _) =+ fail "Promotion of unboxed tuples not supported"++-- to promote a constructor pattern, we need to create extraction type+-- families to pull out the individual arguments of the constructor+promoteTopLevelPat (ConP name pats) = do+ ctorInfo <- reifyWithWarning name+ (ctorType, argTypes) <- extractTypes ctorInfo+ when (length argTypes /= length pats) $+ fail $ "Inconsistent data constructor pattern: " ++ (show name) ++ " " +++ (show pats)+ kind <- promoteType ctorType+ argKinds <- mapM promoteType argTypes+ extractorNames <- replicateM (length pats) (newUniqueName "Extract")++ varName <- qNewName "a"+ zipWithM_ (\nm arg -> addElement $ FamilyD TypeFam+ nm+ [KindedTV varName kind]+ (Just arg))+ extractorNames argKinds+ componentNames <- replicateM (length pats) (qNewName "a")+ zipWithM_ (\extractorName componentName ->+ addElement $ mkTyFamInst extractorName+ [foldType (PromotedT name)+ (map VarT componentNames)]+ (VarT componentName))+ extractorNames componentNames++ -- now we have the extractor families. Use the appropriate families+ -- in the "holes"+ promotedPats <- mapM promoteTopLevelPat pats+ return $ concat $+ zipWith (\lhslist extractor ->+ map (\(LHS raw nm hole) -> LHS raw nm+ (hole . (AppT (ConT extractor))))+ lhslist)+ promotedPats extractorNames+ where extractTypes :: Quasi q => Info -> q (Type, [Type])+ extractTypes (DataConI datacon _dataconTy tyname _fixity) = do+ tyinfo <- reifyWithWarning tyname+ extractTypesHelper datacon tyinfo+ extractTypes _ = fail "Internal error: unexpected Info in extractTypes"++ extractTypesHelper :: Quasi q => Name -> Info -> q (Type, [Type])+ extractTypesHelper datacon+ (TyConI (DataD _cxt tyname tvbs cons _derivs)) =+ let mcon = find ((== datacon) . fst . extractNameArgs) cons in+ case mcon of+ Nothing -> fail $ "Internal error reifying " ++ (show datacon)+ Just con -> return (foldType (ConT tyname)+ (map (VarT . extractTvbName) tvbs),+ extractConArgs con)+ extractTypesHelper datacon+ (TyConI (NewtypeD cxt tyname tvbs con derivs)) =+ extractTypesHelper datacon (TyConI (DataD cxt tyname tvbs [con] derivs))+ extractTypesHelper datacon _ =+ fail $ "Cannot promote data constructor " ++ (show datacon)++ extractConArgs :: Con -> [Type]+ extractConArgs = ctor1Case (\_ tys -> tys)+promoteTopLevelPat (InfixP l name r) = promoteTopLevelPat (ConP name [l, r])+promoteTopLevelPat (UInfixP _ _ _) =+ fail "Unresolved infix constructors not supported"+promoteTopLevelPat (ParensP _) =+ fail "Unresolved infix constructors not supported"+promoteTopLevelPat (TildeP pat) = do+ qReportWarning "Lazy pattern converted into regular pattern in promotion"+ promoteTopLevelPat pat+promoteTopLevelPat (BangP pat) = do+ qReportWarning "Strict pattern converted into regular pattern in promotion"+ promoteTopLevelPat pat+promoteTopLevelPat (AsP _name _pat) =+ fail "Promotion of aliased patterns at top level not yet supported"+promoteTopLevelPat WildP = return []+promoteTopLevelPat (RecP _ _) =+ fail "Promotion of record patterns at top level not yet supported"++-- must do a similar trick as what is in the ConP case, but this is easier+-- because Lib defined Head and Tail+promoteTopLevelPat (ListP pats) = do+ promotedPats <- mapM promoteTopLevelPat pats+ return $ concat $ snd $+ mapAccumL (\extractFn lhss ->+ ((AppT tailTyFam) . extractFn,+ map (\(LHS raw nm hole) ->+ LHS raw nm (hole . (AppT headTyFam) . extractFn)) lhss))+ id promotedPats+promoteTopLevelPat (SigP pat _) = do+ qReportWarning $ "Promotion of explicit type annotation in pattern " +++ "not yet supported."+ promoteTopLevelPat pat+promoteTopLevelPat (ViewP _ _) =+ fail "Promotion of view patterns not yet supported"++type TypesQ q = QWithAux TypeTable q++-- promotes a term pattern into a type pattern, accumulating variable+-- binding in the auxiliary TypeTable+promotePat :: Quasi q => Pat -> TypesQ q Type+promotePat (LitP lit) = promoteLit lit+promotePat (VarP name) = do+ tyVar <- qNewName (nameBase name)+ addBinding name (VarT tyVar)+ return $ VarT tyVar+promotePat (TupP pats) = do+ types <- mapM promotePat pats+ let baseTup = PromotedTupleT (length types)+ tup = foldType baseTup types+ return tup+promotePat (UnboxedTupP _) = fail "Unboxed tuples not supported"+promotePat (ConP name pats) = do+ types <- mapM promotePat pats+ let tyCon = foldType (PromotedT name) types+ return tyCon+promotePat (InfixP pat1 name pat2) = promotePat (ConP name [pat1, pat2])+promotePat (UInfixP _ _ _) = fail "Unresolved infix constructions not supported"+promotePat (ParensP _) = fail "Unresolved infix constructions not supported"+promotePat (TildeP pat) = do+ qReportWarning "Lazy pattern converted into regular pattern in promotion"+ promotePat pat+promotePat (BangP pat) = do+ qReportWarning "Strict pattern converted into regular pattern in promotion"+ promotePat pat+promotePat (AsP name pat) = do+ ty <- promotePat pat+ addBinding name ty+ return ty+promotePat WildP = do+ name <- qNewName "z"+ return $ VarT name+promotePat (RecP _ _) = fail "Promotion of record patterns not yet supported"+promotePat (ListP pats) = do+ types <- mapM promotePat pats+ return $ foldr (\h t -> AppT (AppT PromotedConsT h) t) PromotedNilT types+promotePat (SigP pat _) = do+ qReportWarning $ "Promotion of explicit type annotation in pattern " +++ "not yet supported"+ promotePat pat+promotePat (ViewP _ _) = fail "View patterns not yet supported"++-- promoting a body may produce auxiliary declarations. Accumulate these.+type QWithDecs q = QWithAux [Dec] q++promoteBody :: Quasi q => TypeTable -> Body -> QWithDecs q Type+promoteBody vars (NormalB exp) = promoteExp vars exp+promoteBody _vars (GuardedB _) =+ fail "Promoting guards in patterns not yet supported"++promoteExp :: Quasi q => TypeTable -> Exp -> QWithDecs q Type+promoteExp vars (VarE name) = case Map.lookup name vars of+ Just ty -> return ty+ Nothing -> return $ promoteVal name+promoteExp _vars (ConE name) = return $ PromotedT name+promoteExp _vars (LitE lit) = promoteLit lit+promoteExp vars (AppE exp1 exp2) = do+ ty1 <- promoteExp vars exp1+ ty2 <- promoteExp vars exp2+ return $ AppT ty1 ty2+promoteExp vars (InfixE mexp1 exp mexp2) =+ case (mexp1, mexp2) of+ (Nothing, Nothing) -> promoteExp vars exp+ (Just exp1, Nothing) -> promoteExp vars (AppE exp exp1)+ (Nothing, Just _exp2) ->+ fail "Promotion of right-only sections not yet supported"+ (Just exp1, Just exp2) -> promoteExp vars (AppE (AppE exp exp1) exp2)+promoteExp _vars (UInfixE _ _ _) =+ fail "Promotion of unresolved infix operators not supported"+promoteExp _vars (ParensE _) = fail "Promotion of unresolved parens not supported"+promoteExp _vars (LamE _pats _exp) =+ fail "Promotion of lambda expressions not yet supported"+promoteExp _vars (LamCaseE _alts) =+ fail "Promotion of lambda-case expressions not yet supported"+promoteExp vars (TupE exps) = do+ tys <- mapM (promoteExp vars) exps+ let tuple = PromotedTupleT (length tys)+ tup = foldType tuple tys+ return tup+promoteExp _vars (UnboxedTupE _) = fail "Promotion of unboxed tuples not supported"+promoteExp vars (CondE bexp texp fexp) = do+ tys <- mapM (promoteExp vars) [bexp, texp, fexp]+ return $ foldType ifTyFam tys+promoteExp _vars (MultiIfE _alts) =+ fail "Promotion of multi-way if not yet supported"+promoteExp _vars (LetE _decs _exp) =+ fail "Promotion of let statements not yet supported"+promoteExp _vars (CaseE _exp _matches) =+ fail "Promotion of case statements not yet supported"+promoteExp _vars (DoE _stmts) = fail "Promotion of do statements not supported"+promoteExp _vars (CompE _stmts) =+ fail "Promotion of list comprehensions not yet supported"+promoteExp _vars (ArithSeqE _) = fail "Promotion of ranges not supported"+promoteExp vars (ListE exps) = do+ tys <- mapM (promoteExp vars) exps+ return $ foldr (\ty lst -> AppT (AppT PromotedConsT ty) lst) PromotedNilT tys+promoteExp _vars (SigE _exp _ty) =+ fail "Promotion of explicit type annotations not yet supported"+promoteExp _vars (RecConE _name _fields) =+ fail "Promotion of record construction not yet supported"+promoteExp _vars (RecUpdE _exp _fields) =+ fail "Promotion of record updates not yet supported"++promoteLit :: Monad m => Lit -> m Type+promoteLit (IntegerL n)+ | n >= 0 = return $ LitT (NumTyLit n)+ | otherwise = fail ("Promoting negative integers not supported: " ++ (show n))+promoteLit (StringL str) = return $ LitT (StrTyLit str)+promoteLit lit =+ fail ("Only string and natural number literals can be promoted: " ++ show lit)
+ src/Data/Singletons/Singletons.hs view
@@ -0,0 +1,738 @@+{- Data/Singletons/Singletons.hs++(c) Richard Eisenberg 2013+eir@cis.upenn.edu++This file contains functions to refine constructs to work with singleton+types. It is an internal module to the singletons package.+-}+{-# LANGUAGE TemplateHaskell, CPP, TupleSections #-}++module Data.Singletons.Singletons where++import Prelude hiding ( exp )+import Language.Haskell.TH hiding ( cxt )+import Language.Haskell.TH.Syntax (falseName, trueName, Quasi(..))+import Data.Singletons.Util+import Data.Singletons.Promote+import Data.Singletons+import Data.Singletons.Decide+import qualified Data.Map as Map+import Control.Monad+import Control.Applicative++-- map to track bound variables+type ExpTable = Map.Map Name Exp++-- translating a type gives a type with a hole in it,+-- represented here as a function+type TypeFn = Type -> Type++-- a list of argument types extracted from a type application+type TypeContext = [Type]++singFamilyName, singIName, singMethName, demoteRepName, singKindClassName,+ sEqClassName, sEqMethName, sconsName, snilName, sIfName, undefinedName,+ kProxyDataName, kProxyTypeName, someSingTypeName, someSingDataName,+ nilName, consName, sListName, eqName, sDecideClassName, sDecideMethName,+ provedName, disprovedName, reflName, toSingName, fromSingName, listName :: Name+singFamilyName = ''Sing+singIName = ''SingI+singMethName = 'sing+toSingName = 'toSing+fromSingName = 'fromSing+demoteRepName = ''DemoteRep+singKindClassName = ''SingKind+sEqClassName = mkName "SEq"+sEqMethName = mkName "%:=="+sIfName = mkName "sIf"+undefinedName = 'undefined+sconsName = mkName "SCons"+snilName = mkName "SNil"+kProxyDataName = 'KProxy+kProxyTypeName = ''KProxy+someSingTypeName = ''SomeSing+someSingDataName = 'SomeSing+nilName = '[]+consName = '(:)+listName = ''[]+sListName = mkName "SList"+eqName = ''Eq+sDecideClassName = ''SDecide+sDecideMethName = '(%~)+provedName = 'Proved+disprovedName = 'Disproved+reflName = 'Refl++mkTupleName :: Int -> Name+mkTupleName n = mkName $ "STuple" ++ (show n)++singFamily :: Type+singFamily = ConT singFamilyName++singKindConstraint :: Kind -> Pred+singKindConstraint k = ClassP singKindClassName [kindParam k]++demote :: Type+demote = ConT demoteRepName++singDataConName :: Name -> Name+singDataConName nm+ | nm == nilName = snilName+ | nm == consName = sconsName+ | Just degree <- tupleNameDegree_maybe nm = mkTupleName degree+ | otherwise = prefixUCName "S" ":%" nm++singTyConName :: Name -> Name+singTyConName name+ | name == listName = sListName+ | Just degree <- tupleNameDegree_maybe name = mkTupleName degree+ | otherwise = prefixUCName "S" ":%" name++singClassName :: Name -> Name+singClassName = singTyConName++singDataCon :: Name -> Exp+singDataCon = ConE . singDataConName++singValName :: Name -> Name+singValName n+ | nameBase n == "undefined" = undefinedName+ | otherwise = (prefixLCName "s" "%") $ upcase n++singVal :: Name -> Exp+singVal = VarE . singValName++kindParam :: Kind -> Type+kindParam k = SigT (ConT kProxyDataName) (AppT (ConT kProxyTypeName) k)++-- | Generate singleton definitions from a type that is already defined.+-- For example, the singletons package itself uses+--+-- > $(genSingletons [''Bool, ''Maybe, ''Either, ''[]])+--+-- to generate singletons for Prelude types.+genSingletons :: Quasi q => [Name] -> q [Dec]+genSingletons names = do+ checkForRep names+ concatMapM (singInfo <=< reifyWithWarning) names++singInfo :: Quasi q => Info -> q [Dec]+singInfo (ClassI _dec _instances) =+ fail "Singling of class info not supported"+singInfo (ClassOpI _name _ty _className _fixity) =+ fail "Singling of class members info not supported"+singInfo (TyConI dec) = singDec dec+singInfo (FamilyI _dec _instances) =+ fail "Singling of type family info not yet supported" -- KindFams+singInfo (PrimTyConI _name _numArgs _unlifted) =+ fail "Singling of primitive type constructors not supported"+singInfo (DataConI _name _ty _tyname _fixity) =+ fail $ "Singling of individual constructors not supported; " +++ "single the type instead"+singInfo (VarI _name _ty _mdec _fixity) =+ fail "Singling of value info not supported"+singInfo (TyVarI _name _ty) =+ fail "Singling of type variable info not supported"++-- refine a constructor. the first parameter is the type variable that+-- the singleton GADT is parameterized by+-- runs in the QWithDecs monad because auxiliary declarations are produced+singCtor :: Quasi q => Type -> Con -> QWithDecs q Con+singCtor a = ctorCases+ -- monomorphic case+ (\name types -> do+ let sName = singDataConName name+ sCon = singDataCon name+ pCon = PromotedT name+ indexNames <- replicateM (length types) (qNewName "n")+ let indices = map VarT indexNames+ kinds <- mapM promoteType types+ args <- buildArgTypes types indices+ let tvbs = zipWith KindedTV indexNames kinds+ kindedIndices = zipWith SigT indices kinds++ -- SingI instance+ addElement $ InstanceD (map (ClassP singIName . listify) indices)+ (AppT (ConT singIName)+ (foldType pCon kindedIndices))+ [ValD (VarP singMethName)+ (NormalB $ foldExp sCon (replicate (length types)+ (VarE singMethName)))+ []]++ return $ ForallC tvbs+ [EqualP a (foldType pCon indices)]+ (NormalC sName $ map (NotStrict,) args))++ -- polymorphic case+ (\_tvbs cxt ctor -> case cxt of+ _:_ -> fail "Singling of constrained constructors not yet supported"+ [] -> singCtor a ctor) -- polymorphic constructors are handled just+ -- like monomorphic ones -- the polymorphism in+ -- the kind is automatic+ where buildArgTypes :: Quasi q => [Type] -> [Type] -> q [Type]+ buildArgTypes types indices = do+ typeFns <- mapM singType types+ return $ zipWith id typeFns indices++-- | Make promoted and singleton versions of all declarations given, retaining+-- the original declarations.+-- See <http://www.cis.upenn.edu/~eir/packages/singletons/README.html> for+-- further explanation.+singletons :: Quasi q => q [Dec] -> q [Dec]+singletons = (>>= singDecs True)++-- | Make promoted and singleton versions of all declarations given, discarding+-- the original declarations.+singletonsOnly :: Quasi q => q [Dec] -> q [Dec]+singletonsOnly = (>>= singDecs False)++-- first parameter says whether or not to include original decls+singDecs :: Quasi q => Bool -> [Dec] -> q [Dec]+singDecs originals decls = do+ promDecls <- promoteDecs decls+ newDecls <- mapM singDec decls+ return $ (if originals then (decls ++) else id) $ promDecls ++ (concat newDecls)++singDec :: Quasi q => Dec -> q [Dec]+singDec (FunD name clauses) = do+ let sName = singValName name+ vars = Map.singleton name (VarE sName)+ listify <$> FunD sName <$> (mapM (singClause vars) clauses)+singDec (ValD _ (GuardedB _) _) =+ fail "Singling of definitions of values with a pattern guard not yet supported"+singDec (ValD _ _ (_:_)) =+ fail "Singling of definitions of values with a <<where>> clause not yet supported"+singDec (ValD pat (NormalB exp) []) = do+ (sPat, vartbl) <- evalForPair $ singPat TopLevel pat+ sExp <- singExp vartbl exp+ return [ValD sPat (NormalB sExp) []]+singDec (DataD cxt name tvbs ctors derivings) =+ singDataD False cxt name tvbs ctors derivings+singDec (NewtypeD cxt name tvbs ctor derivings) =+ singDataD False cxt name tvbs [ctor] derivings+singDec (TySynD _name _tvbs _ty) =+ fail "Singling of type synonyms not yet supported"+singDec (ClassD _cxt _name _tvbs _fundeps _decs) =+ fail "Singling of class declaration not yet supported"+singDec (InstanceD _cxt _ty _decs) =+ fail "Singling of class instance not yet supported"+singDec (SigD name ty) = do+ tyTrans <- singType ty+ return [SigD (singValName name) (tyTrans (promoteVal name))]+singDec (ForeignD fgn) =+ let name = extractName fgn in do+ qReportWarning $ "Singling of foreign functions not supported -- " +++ (show name) ++ " ignored"+ return []+ where extractName :: Foreign -> Name+ extractName (ImportF _ _ _ n _) = n+ extractName (ExportF _ _ n _) = n+singDec (InfixD fixity name)+ | isUpcase name = return [InfixD fixity (singDataConName name)]+ | otherwise = return [InfixD fixity (singValName name)]+singDec (PragmaD _prag) = do+ qReportWarning "Singling of pragmas not supported"+ return []+singDec (FamilyD _flavour _name _tvbs _mkind) =+ fail "Singling of type and data families not yet supported"+singDec (DataInstD _cxt _name _tys _ctors _derivings) =+ fail "Singling of data instances not yet supported"+singDec (NewtypeInstD _cxt _name _tys _ctor _derivings) =+ fail "Singling of newtype instances not yet supported"+#if __GLASGOW_HASKELL__ >= 707+singDec (RoleAnnotD _name _roles) =+ return [] -- silently ignore role annotations, as they're harmless+singDec (ClosedTypeFamilyD _name _tvs _mkind _eqns) =+ fail "Singling of closed type families not yet supported"+singDec (TySynInstD _name _eqns) =+#else+singDec (TySynInstD _name _lhs _rhs) =+#endif+ fail "Singling of type family instances not yet supported"++-- | Create instances of 'SEq' and type-level '(:==)' for each type in the list+singEqInstances :: Quasi q => [Name] -> q [Dec]+singEqInstances = concatMapM singEqInstance++-- | Create instance of 'SEq' and type-level '(:==)' for the given type+singEqInstance :: Quasi q => Name -> q [Dec]+singEqInstance name = do+ promotion <- promoteEqInstance name+ dec <- singEqualityInstance sEqClassDesc name+ return $ dec : promotion++-- | Create instances of 'SEq' (only -- no instance for '(:==)', which 'SEq' generally+-- relies on) for each type in the list+singEqInstancesOnly :: Quasi q => [Name] -> q [Dec]+singEqInstancesOnly = concatMapM singEqInstanceOnly++-- | Create instances of 'SEq' (only -- no instance for '(:==)', which 'SEq' generally+-- relies on) for the given type+singEqInstanceOnly :: Quasi q => Name -> q [Dec]+singEqInstanceOnly name = listify <$> singEqualityInstance sEqClassDesc name++-- | Create instances of 'SDecide' for each type in the list.+--+-- Note that, due to a bug in GHC 7.6.3 (and lower) optimizing instances+-- for SDecide can make GHC hang. You may want to put+-- @{-# OPTIONS_GHC -O0 #-}@ in your file.+singDecideInstances :: Quasi q => [Name] -> q [Dec]+singDecideInstances = concatMapM singDecideInstance++-- | Create instance of 'SDecide' for the given type.+--+-- Note that, due to a bug in GHC 7.6.3 (and lower) optimizing instances+-- for SDecide can make GHC hang. You may want to put+-- @{-# OPTIONS_GHC -O0 #-}@ in your file.+singDecideInstance :: Quasi q => Name -> q [Dec]+singDecideInstance name = listify <$> singEqualityInstance sDecideClassDesc name++-- generalized function for creating equality instances+singEqualityInstance :: Quasi q => EqualityClassDesc q -> Name -> q Dec+singEqualityInstance desc@(_, className, _) name = do+ (tvbs, cons) <- getDataD ("I cannot make an instance of " +++ show className ++ " for it.") name+ let tyvars = map (VarT . extractTvbName) tvbs+ kind = foldType (ConT name) tyvars+ aName <- qNewName "a"+ let aVar = VarT aName+ scons <- mapM (evalWithoutAux . singCtor aVar) cons+ mkEqualityInstance kind scons desc++-- making the SEq instance and the SDecide instance are rather similar,+-- so we generalize+type EqualityClassDesc q = ((Con, Con) -> q Clause, Name, Name)+sEqClassDesc, sDecideClassDesc :: Quasi q => EqualityClassDesc q+sEqClassDesc = (mkEqMethClause, sEqClassName, sEqMethName)+sDecideClassDesc = (mkDecideMethClause, sDecideClassName, sDecideMethName)++-- pass the *singleton* constructors, not the originals+mkEqualityInstance :: Quasi q => Kind -> [Con]+ -> EqualityClassDesc q -> q Dec+mkEqualityInstance k ctors (mkMeth, className, methName) = do+ let ctorPairs = [ (c1, c2) | c1 <- ctors, c2 <- ctors ]+ methClauses <- if null ctors+ then mkEmptyMethClauses+ else mapM mkMeth ctorPairs+ return $ InstanceD (map (\kvar -> ClassP className [kindParam kvar])+ (getKindVars k))+ (AppT (ConT className)+ (kindParam k))+ [FunD methName methClauses]+ where getKindVars :: Kind -> [Kind]+ getKindVars (AppT l r) = getKindVars l ++ getKindVars r+ getKindVars (VarT x) = [VarT x]+ getKindVars (ConT _) = []+ getKindVars StarT = []+ getKindVars other =+ error ("getKindVars sees an unusual kind: " ++ show other)++ mkEmptyMethClauses :: Quasi q => q [Clause]+ mkEmptyMethClauses = do+ a <- qNewName "a"+ return [Clause [VarP a, WildP] (NormalB (CaseE (VarE a) emptyMatches)) []]++mkEqMethClause :: Quasi q => (Con, Con) -> q Clause+mkEqMethClause (c1, c2)+ | lname == rname = do+ lnames <- replicateM lNumArgs (qNewName "a")+ rnames <- replicateM lNumArgs (qNewName "b")+ let lpats = map VarP lnames+ rpats = map VarP rnames+ lvars = map VarE lnames+ rvars = map VarE rnames+ return $ Clause+ [ConP lname lpats, ConP rname rpats]+ (NormalB $+ allExp (zipWith (\l r -> foldExp (VarE sEqMethName) [l, r])+ lvars rvars))+ []+ | otherwise =+ return $ Clause+ [ConP lname (replicate lNumArgs WildP),+ ConP rname (replicate rNumArgs WildP)]+ (NormalB (singDataCon falseName))+ []+ where allExp :: [Exp] -> Exp+ allExp [] = singDataCon trueName+ allExp [one] = one+ allExp (h:t) = AppE (AppE (singVal andName) h) (allExp t)++ (lname, lNumArgs) = extractNameArgs c1+ (rname, rNumArgs) = extractNameArgs c2++mkDecideMethClause :: Quasi q => (Con, Con) -> q Clause+mkDecideMethClause (c1, c2)+ | lname == rname =+ if lNumArgs == 0+ then return $ Clause [ConP lname [], ConP rname []]+ (NormalB (AppE (ConE provedName) (ConE reflName))) []+ else do+ lnames <- replicateM lNumArgs (qNewName "a")+ rnames <- replicateM lNumArgs (qNewName "b")+ contra <- qNewName "contra"+ let lpats = map VarP lnames+ rpats = map VarP rnames+ lvars = map VarE lnames+ rvars = map VarE rnames+ return $ Clause+ [ConP lname lpats, ConP rname rpats]+ (NormalB $+ CaseE (mkTupleExp $+ zipWith (\l r -> foldExp (VarE sDecideMethName) [l, r])+ lvars rvars)+ ((Match (mkTuplePat (replicate lNumArgs+ (ConP provedName [ConP reflName []])))+ (NormalB $ AppE (ConE provedName) (ConE reflName))+ []) :+ [Match (mkTuplePat (replicate i WildP +++ ConP disprovedName [VarP contra] :+ replicate (lNumArgs - i - 1) WildP))+ (NormalB $ AppE (ConE disprovedName)+ (LamE [ConP reflName []]+ (AppE (VarE contra)+ (ConE reflName))))+ [] | i <- [0..lNumArgs-1] ]))+ []++ | otherwise =+ return $ Clause+ [ConP lname (replicate lNumArgs WildP),+ ConP rname (replicate rNumArgs WildP)]+ (NormalB (AppE (ConE disprovedName) (LamCaseE emptyMatches)))+ []++ where+ (lname, lNumArgs) = extractNameArgs c1+ (rname, rNumArgs) = extractNameArgs c2++-- the first parameter is True when we're refining the special case "Rep"+-- and false otherwise. We wish to consider the promotion of "Rep" to be *+-- not a promoted data constructor.+singDataD :: Quasi q => Bool -> Cxt -> Name -> [TyVarBndr] -> [Con] -> [Name] -> q [Dec]+singDataD rep cxt name tvbs ctors derivings+ | (_:_) <- cxt = fail "Singling of constrained datatypes is not supported"+ | otherwise = do+ aName <- qNewName "z"+ let a = VarT aName+ let tvbNames = map extractTvbName tvbs+ k <- promoteType (foldType (ConT name) (map VarT tvbNames))+ (ctors', ctorInstDecls) <- evalForPair $ mapM (singCtor a) ctors++ -- instance for SingKind+ fromSingClauses <- mapM mkFromSingClause ctors+ toSingClauses <- mapM mkToSingClause ctors+ let singKindInst =+ InstanceD (map (singKindConstraint . VarT) tvbNames)+ (AppT (ConT singKindClassName)+ (kindParam k))+ [ mkTyFamInst demoteRepName+ [kindParam k]+ (foldType (ConT name)+ (map (AppT demote . kindParam . VarT) tvbNames))+ , FunD fromSingName (fromSingClauses `orIfEmpty` emptyMethod aName)+ , FunD toSingName (toSingClauses `orIfEmpty` emptyMethod aName) ]++ -- SEq instance+ sEqInsts <- if elem eqName derivings+ then mapM (mkEqualityInstance k ctors') [sEqClassDesc, sDecideClassDesc]+ else return []++ -- e.g. type SNat (a :: Nat) = Sing a+ let kindedSynInst =+ TySynD (singTyConName name)+ [KindedTV aName k]+ (AppT singFamily a)++ return $ (DataInstD [] singFamilyName [SigT a k] ctors' []) :+ kindedSynInst :+ singKindInst :+ sEqInsts +++ ctorInstDecls+ where -- in the Rep case, the names of the constructors are in the wrong scope+ -- (they're types, not datacons), so we have to reinterpret them.+ mkConName :: Name -> Name+ mkConName = if rep then reinterpret else id++ mkFromSingClause :: Quasi q => Con -> q Clause+ mkFromSingClause c = do+ let (cname, numArgs) = extractNameArgs c+ varNames <- replicateM numArgs (qNewName "b")+ return $ Clause [ConP (singDataConName cname) (map VarP varNames)]+ (NormalB $ foldExp+ (ConE $ mkConName cname)+ (map (AppE (VarE fromSingName) . VarE) varNames))+ []++ mkToSingClause :: Quasi q => Con -> q Clause+ mkToSingClause = ctor1Case $ \cname types -> do+ varNames <- mapM (const $ qNewName "b") types+ svarNames <- mapM (const $ qNewName "c") types+ promoted <- mapM promoteType types+ let recursiveCalls = zipWith mkRecursiveCall varNames promoted+ return $+ Clause [ConP (mkConName cname) (map VarP varNames)]+ (NormalB $+ multiCase recursiveCalls+ (map (ConP someSingDataName . listify . VarP)+ svarNames)+ (AppE (ConE someSingDataName)+ (foldExp (ConE (singDataConName cname))+ (map VarE svarNames))))+ []++ mkRecursiveCall :: Name -> Kind -> Exp+ mkRecursiveCall var_name ki =+ SigE (AppE (VarE toSingName) (VarE var_name))+ (AppT (ConT someSingTypeName) (kindParam ki))++ emptyMethod :: Name -> [Clause]+ emptyMethod n = [Clause [VarP n] (NormalB $ CaseE (VarE n) emptyMatches) []]++singKind :: Quasi q => Kind -> q (Kind -> Kind)+singKind (ForallT _ _ _) =+ fail "Singling of explicitly quantified kinds not yet supported"+singKind (VarT _) = fail "Singling of kind variables not yet supported"+singKind (ConT _) = fail "Singling of named kinds not yet supported"+singKind (TupleT _) = fail "Singling of tuple kinds not yet supported"+singKind (UnboxedTupleT _) = fail "Unboxed tuple used as kind"+singKind ArrowT = fail "Singling of unsaturated arrow kinds not yet supported"+singKind ListT = fail "Singling of list kinds not yet supported"+singKind (AppT (AppT ArrowT k1) k2) = do+ k1fn <- singKind k1+ k2fn <- singKind k2+ k <- qNewName "k"+ return $ \f -> AppT (AppT ArrowT (k1fn (VarT k))) (k2fn (AppT f (VarT k)))+singKind (AppT _ _) = fail "Singling of kind applications not yet supported"+singKind (SigT _ _) =+ fail "Singling of explicitly annotated kinds not yet supported"+singKind (LitT _) = fail "Type literal used as kind"+singKind (PromotedT _) = fail "Promoted data constructor used as kind"+singKind (PromotedTupleT _) = fail "Promoted tuple used as kind"+singKind PromotedNilT = fail "Promoted nil used as kind"+singKind PromotedConsT = fail "Promoted cons used as kind"+singKind StarT = return $ \k -> AppT (AppT ArrowT k) StarT+singKind ConstraintT = fail "Singling of constraint kinds not yet supported"++singType :: Quasi q => Type -> q TypeFn+singType ty = do -- replace with singTypeRec [] ty after GHC bug #??? is fixed+ sTypeFn <- singTypeRec [] ty+ return $ \inner_ty -> liftOutForalls $ sTypeFn inner_ty++-- Lifts all foralls to the top-level. This is a workaround for bug #8031 on GHC+-- Trac+liftOutForalls :: Type -> Type+liftOutForalls =+ go [] [] []+ where+ go tyvars cxt args (ForallT tyvars1 cxt1 t1)+ = go (reverse tyvars1 ++ tyvars) (reverse cxt1 ++ cxt) args t1+ go tyvars cxt args (SigT t1 _kind) -- ignore these kind annotations, which have to be *+ = go tyvars cxt args t1+ go tyvars cxt args (AppT (AppT ArrowT arg1) res1)+ = go tyvars cxt (arg1 : args) res1+ go [] [] args t1+ = mk_fun_ty (reverse args) t1+ go tyvars cxt args t1+ = ForallT (reverse tyvars) (reverse cxt) (mk_fun_ty (reverse args) t1)++ mk_fun_ty [] res = res+ mk_fun_ty (arg1:args) res = AppT (AppT ArrowT arg1) (mk_fun_ty args res)++-- the first parameter is the list of types the current type is applied to+singTypeRec :: Quasi q => TypeContext -> Type -> q TypeFn+singTypeRec (_:_) (ForallT _ _ _) =+ fail "I thought this was impossible in Haskell. Email me at eir@cis.upenn.edu with your code if you see this message."+singTypeRec [] (ForallT _ [] ty) = -- Sing makes handling foralls automatic+ singTypeRec [] ty+singTypeRec ctx (ForallT _tvbs cxt innerty) = do+ cxt' <- singContext cxt+ innerty' <- singTypeRec ctx innerty+ return $ \ty -> ForallT [] cxt' (innerty' ty)+singTypeRec (_:_) (VarT _) =+ fail "Singling of type variables of arrow kinds not yet supported"+singTypeRec [] (VarT _name) =+ return $ \ty -> AppT singFamily ty+singTypeRec _ctx (ConT _name) = -- we don't need to process the context with Sing+ return $ \ty -> AppT singFamily ty+singTypeRec _ctx (TupleT _n) = -- just like ConT+ return $ \ty -> AppT singFamily ty+singTypeRec _ctx (UnboxedTupleT _n) =+ fail "Singling of unboxed tuple types not yet supported"+singTypeRec ctx ArrowT = case ctx of+ [ty1, ty2] -> do+ t <- qNewName "t"+ sty1 <- singTypeRec [] ty1+ sty2 <- singTypeRec [] ty2+ k1 <- promoteType ty1+ return (\f -> ForallT [KindedTV t k1]+ []+ (AppT (AppT ArrowT (sty1 (VarT t)))+ (sty2 (AppT f (VarT t)))))+ _ -> fail "Internal error in Sing: converting ArrowT with improper context"+singTypeRec _ctx ListT =+ return $ \ty -> AppT singFamily ty+singTypeRec ctx (AppT ty1 ty2) =+ singTypeRec (ty2 : ctx) ty1 -- recur with the ty2 in the applied context+singTypeRec _ctx (SigT _ty _knd) =+ fail "Singling of types with explicit kinds not yet supported"+singTypeRec _ctx (LitT _) = fail "Singling of type-level literals not yet supported"+singTypeRec _ctx (PromotedT _) =+ fail "Singling of promoted data constructors not yet supported"+singTypeRec _ctx (PromotedTupleT _) =+ fail "Singling of type-level tuples not yet supported"+singTypeRec _ctx PromotedNilT = fail "Singling of promoted nil not yet supported"+singTypeRec _ctx PromotedConsT = fail "Singling of type-level cons not yet supported"+singTypeRec _ctx StarT = fail "* used as type"+singTypeRec _ctx ConstraintT = fail "Constraint used as type"++-- refine a constraint context+singContext :: Quasi q => Cxt -> q Cxt+singContext = mapM singPred++singPred :: Quasi q => Pred -> q Pred+singPred (ClassP name tys) = do+ kis <- mapM promoteType tys+ let sName = singClassName name+ return $ ClassP sName (map kindParam kis)+singPred (EqualP _ty1 _ty2) =+ fail "Singling of type equality constraints not yet supported"++singClause :: Quasi q => ExpTable -> Clause -> q Clause+singClause vars (Clause pats (NormalB exp) []) = do+ (sPats, vartbl) <- evalForPair $ mapM (singPat Parameter) pats+ let vars' = Map.union vartbl vars+ sBody <- NormalB <$> singExp vars' exp+ return $ Clause sPats sBody []+singClause _ (Clause _ (GuardedB _) _) =+ fail "Singling of guarded patterns not yet supported"+singClause _ (Clause _ _ (_:_)) =+ fail "Singling of <<where>> declarations not yet supported"++type ExpsQ q = QWithAux ExpTable q++-- we need to know where a pattern is to anticipate when+-- GHC's brain might explode+data PatternContext = LetBinding+ | CaseStatement+ | TopLevel+ | Parameter+ | Statement+ deriving Eq++checkIfBrainWillExplode :: Quasi q => PatternContext -> ExpsQ q ()+checkIfBrainWillExplode CaseStatement = return ()+checkIfBrainWillExplode Statement = return ()+checkIfBrainWillExplode Parameter = return ()+checkIfBrainWillExplode _ =+ fail $ "Can't use a singleton pattern outside of a case-statement or\n" +++ "do expression: GHC's brain will explode if you try. (Do try it!)"++-- convert a pattern, building up the lexical scope as we go+singPat :: Quasi q => PatternContext -> Pat -> ExpsQ q Pat+singPat _patCxt (LitP _lit) =+ fail "Singling of literal patterns not yet supported"+singPat patCxt (VarP name) =+ let new = if patCxt == TopLevel then singValName name else name in do+ addBinding name (VarE new)+ return $ VarP new+singPat patCxt (TupP pats) =+ singPat patCxt (ConP (tupleDataName (length pats)) pats)+singPat _patCxt (UnboxedTupP _pats) =+ fail "Singling of unboxed tuples not supported"+singPat patCxt (ConP name pats) = do+ checkIfBrainWillExplode patCxt+ pats' <- mapM (singPat patCxt) pats+ return $ ConP (singDataConName name) pats'+singPat patCxt (InfixP pat1 name pat2) = singPat patCxt (ConP name [pat1, pat2])+singPat _patCxt (UInfixP _ _ _) =+ fail "Singling of unresolved infix patterns not supported"+singPat _patCxt (ParensP _) =+ fail "Singling of unresolved paren patterns not supported"+singPat patCxt (TildeP pat) = do+ pat' <- singPat patCxt pat+ return $ TildeP pat'+singPat patCxt (BangP pat) = do+ pat' <- singPat patCxt pat+ return $ BangP pat'+singPat patCxt (AsP name pat) = do+ let new = if patCxt == TopLevel then singValName name else name in do+ pat' <- singPat patCxt pat+ addBinding name (VarE new)+ return $ AsP name pat'+singPat _patCxt WildP = return WildP+singPat _patCxt (RecP _name _fields) =+ fail "Singling of record patterns not yet supported"+singPat patCxt (ListP pats) = do+ checkIfBrainWillExplode patCxt+ sPats <- mapM (singPat patCxt) pats+ return $ foldr (\elt lst -> ConP sconsName [elt, lst]) (ConP snilName []) sPats+singPat _patCxt (SigP _pat _ty) =+ fail "Singling of annotated patterns not yet supported"+singPat _patCxt (ViewP _exp _pat) =+ fail "Singling of view patterns not yet supported"++singExp :: Quasi q => ExpTable -> Exp -> q Exp+singExp vars (VarE name) = case Map.lookup name vars of+ Just exp -> return exp+ Nothing -> return (singVal name)+singExp _vars (ConE name) = return $ singDataCon name+singExp _vars (LitE lit) = singLit lit+singExp vars (AppE exp1 exp2) = do+ exp1' <- singExp vars exp1+ exp2' <- singExp vars exp2+ return $ AppE exp1' exp2'+singExp vars (InfixE mexp1 exp mexp2) =+ case (mexp1, mexp2) of+ (Nothing, Nothing) -> singExp vars exp+ (Just exp1, Nothing) -> singExp vars (AppE exp exp1)+ (Nothing, Just _exp2) ->+ fail "Singling of right-only sections not yet supported"+ (Just exp1, Just exp2) -> singExp vars (AppE (AppE exp exp1) exp2)+singExp _vars (UInfixE _ _ _) =+ fail "Singling of unresolved infix expressions not supported"+singExp _vars (ParensE _) =+ fail "Singling of unresolved paren expressions not supported"+singExp vars (LamE pats exp) = do+ (pats', vartbl) <- evalForPair $ mapM (singPat Parameter) pats+ let vars' = Map.union vartbl vars -- order matters; union is left-biased+ exp' <- singExp vars' exp+ return $ LamE pats' exp'+singExp _vars (LamCaseE _matches) =+ fail "Singling of case expressions not yet supported"+singExp vars (TupE exps) = do+ sExps <- mapM (singExp vars) exps+ sTuple <- singExp vars (ConE (tupleDataName (length exps)))+ return $ foldExp sTuple sExps+singExp _vars (UnboxedTupE _exps) =+ fail "Singling of unboxed tuple not supported"+singExp vars (CondE bexp texp fexp) = do+ exps <- mapM (singExp vars) [bexp, texp, fexp]+ return $ foldExp (VarE sIfName) exps+singExp _vars (MultiIfE _alts) =+ fail "Singling of multi-way if statements not yet supported"+singExp _vars (LetE _decs _exp) =+ fail "Singling of let expressions not yet supported"+singExp _vars (CaseE _exp _matches) =+ fail "Singling of case expressions not yet supported"+singExp _vars (DoE _stmts) =+ fail "Singling of do expressions not yet supported"+singExp _vars (CompE _stmts) =+ fail "Singling of list comprehensions not yet supported"+singExp _vars (ArithSeqE _range) =+ fail "Singling of ranges not yet supported"+singExp vars (ListE exps) = do+ sExps <- mapM (singExp vars) exps+ return $ foldr (\x -> (AppE (AppE (ConE sconsName) x)))+ (ConE snilName) sExps+singExp _vars (SigE _exp _ty) =+ fail "Singling of annotated expressions not yet supported"+singExp _vars (RecConE _name _fields) =+ fail "Singling of record construction not yet supported"+singExp _vars (RecUpdE _exp _fields) =+ fail "Singling of record updates not yet supported"++singLit :: Quasi q => Lit -> q Exp+singLit lit = SigE (VarE singMethName) <$> (AppT singFamily <$> (promoteLit lit))
+ src/Data/Singletons/TH.hs view
@@ -0,0 +1,86 @@+{-# LANGUAGE ExplicitNamespaces, CPP #-}++-----------------------------------------------------------------------------+-- |+-- Module : Data.Singletons.TH+-- Copyright : (C) 2013 Richard Eisenberg+-- License : BSD-style (see LICENSE)+-- Maintainer : Richard Eisenberg (eir@cis.upenn.edu)+-- Stability : experimental+-- Portability : non-portable+--+-- This module contains everything you need to derive your own singletons via+-- Template Haskell.+--+-- TURN ON @-XScopedTypeVariables@ IN YOUR MODULE IF YOU WANT THIS TO WORK.+--+----------------------------------------------------------------------------++module Data.Singletons.TH (+ -- * Primary Template Haskell generation functions+ singletons, singletonsOnly, genSingletons,+ promote, promoteOnly,++ -- ** Functions to generate equality instances+ promoteEqInstances, promoteEqInstance,+ singEqInstances, singEqInstance,+ singEqInstancesOnly, singEqInstanceOnly,+ singDecideInstances, singDecideInstance,++ -- ** Utility function+ cases,++ -- * Basic singleton definitions+ Sing(SFalse, STrue), SingI(..), SingKind(..), KindOf, Demote,++ -- * Auxiliary definitions+ -- | These definitions might be mentioned in code generated by Template Haskell,+ -- so they must be in scope.++ type (==), (:==), If, sIf, (:&&), SEq(..),+ Any,+ SDecide(..), (:~:)(..), Void, Refuted, Decision(..),+ KProxy(..), SomeSing(..)+ ) where++import Data.Singletons+import Data.Singletons.Singletons+import Data.Singletons.Promote+import Data.Singletons.Instances+import Data.Singletons.Bool+import Data.Singletons.Eq+import Data.Singletons.Types+import Data.Singletons.Void+import Data.Singletons.Decide++import GHC.Exts+import Language.Haskell.TH+import Language.Haskell.TH.Syntax ( Quasi(..) )+import Language.Haskell.TH.Desugar+import Data.Singletons.Util+import Control.Applicative++-- | The function 'cases' generates a case expression where each right-hand side+-- is identical. This may be useful if the type-checker requires knowledge of which+-- constructor is used to satisfy equality or type-class constraints, but where+-- each constructor is treated the same.+cases :: Quasi q+ => Name -- ^ The head of the type of the scrutinee. (Like @''Maybe@ or @''Bool@.)+ -> q Exp -- ^ The scrutinee, in a Template Haskell quote+ -> q Exp -- ^ The body, in a Template Haskell quote+ -> q Exp+cases tyName expq bodyq = do+ info <- reifyWithWarning tyName+ case info of+ TyConI (DataD _ _ _ ctors _) -> buildCases ctors+ TyConI (NewtypeD _ _ _ ctor _) -> buildCases [ctor]+ _ -> fail $ "Using <<cases>> with something other than a type constructor: "+ ++ (show tyName)+ where buildCases ctors =+ CaseE <$> expq <*>+ mapM (\con -> Match (conToPat con) <$>+ (NormalB <$> bodyq) <*> pure []) ctors++ conToPat :: Con -> Pat+ conToPat = ctor1Case+ (\name tys -> ConP name (map (const WildP) tys))
+ src/Data/Singletons/Tuple.hs view
@@ -0,0 +1,61 @@+{-# LANGUAGE TemplateHaskell, ScopedTypeVariables, DataKinds, PolyKinds,+ RankNTypes, TypeFamilies, GADTs, CPP #-}++#if __GLASGOW_HASKELL__ < 707+{-# OPTIONS_GHC -fno-warn-name-shadowing #-}+#endif++-----------------------------------------------------------------------------+-- |+-- Module : Data.Singletons.Tuple+-- Copyright : (C) 2013 Richard Eisenberg+-- License : BSD-style (see LICENSE)+-- Maintainer : Richard Eisenberg (eir@cis.upenn.edu)+-- Stability : experimental+-- Portability : non-portable+--+-- Defines functions and datatypes relating to the singleton for tuples,+-- including a singletons version of all the definitions in @Data.Tuple@.+--+-- Because many of these definitions are produced by Template Haskell,+-- it is not possible to create proper Haddock documentation. Please look+-- up the corresponding operation in @Data.Tuple@. Also, please excuse+-- the apparent repeated variable names. This is due to an interaction+-- between Template Haskell and Haddock.+--+----------------------------------------------------------------------------++module Data.Singletons.Tuple (+ -- * Singleton definitions+ -- | See 'Data.Singletons.Prelude.Sing' for more info.+ Sing(STuple0, STuple2, STuple3, STuple4, STuple5, STuple6, STuple7),+ STuple0, STuple2, STuple3, STuple4, STuple5, STuple6, STuple7,++ -- * Singletons from @Data.Tuple@+ Fst, sFst, Snd, sSnd, Curry, sCurry, Uncurry, sUncurry, Swap, sSwap+ ) where++import Data.Singletons.Instances+import Data.Singletons.TH++$(singletonsOnly [d|+ -- | Extract the first component of a pair.+ fst :: (a,b) -> a+ fst (x,_) = x++ -- | Extract the second component of a pair.+ snd :: (a,b) -> b+ snd (_,y) = y++ -- | 'curry' converts an uncurried function to a curried function.+ curry :: ((a, b) -> c) -> a -> b -> c+ curry f x y = f (x, y)++ -- | 'uncurry' converts a curried function to a function on pairs.+ uncurry :: (a -> b -> c) -> ((a, b) -> c)+ uncurry f p = f (fst p) (snd p)++ -- | Swap the components of a pair.+ swap :: (a,b) -> (b,a)+ swap (a,b) = (b,a)+ |])
+ src/Data/Singletons/TypeLits.hs view
@@ -0,0 +1,181 @@+-----------------------------------------------------------------------------+-- |+-- Module : Data.Singletons.TypeLits+-- Copyright : (C) 2014 Richard Eisenberg+-- License : BSD-style (see LICENSE)+-- Maintainer : Richard Eisenberg (eir@cis.upenn.edu)+-- Stability : experimental+-- Portability : non-portable+--+-- Defines and exports singletons useful for the Nat and Symbol kinds.+--+----------------------------------------------------------------------------++{-# LANGUAGE CPP, PolyKinds, DataKinds, TypeFamilies, FlexibleInstances,+ UndecidableInstances, ScopedTypeVariables, RankNTypes,+ GADTs, FlexibleContexts #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}++#if __GLASGOW_HASKELL__ < 707+{-# OPTIONS_GHC -O0 #-} -- don't optimize SDecide instances in 7.6!+#endif++module Data.Singletons.TypeLits (+ Nat, Symbol,+ SNat, SSymbol, withKnownNat, withKnownSymbol,+ Error, sError,+ KnownNat, natVal, KnownSymbol, symbolVal+ ) where++import Data.Singletons+import Data.Singletons.Types+import Data.Singletons.Eq+import Data.Singletons.Decide+import Data.Singletons.Bool+#if __GLASGOW_HASKELL__ >= 707+import GHC.TypeLits+#else+import GHC.TypeLits (Nat, Symbol)+import qualified GHC.TypeLits as TL+#endif+import Unsafe.Coerce++----------------------------------------------------------------------+---- TypeLits singletons ---------------------------------------------+----------------------------------------------------------------------++#if __GLASGOW_HASKELL__ >= 707+data instance Sing (n :: Nat) = KnownNat n => SNat++instance KnownNat n => SingI n where+ sing = SNat++instance SingKind ('KProxy :: KProxy Nat) where+ type DemoteRep ('KProxy :: KProxy Nat) = Integer+ fromSing (SNat :: Sing n) = natVal (Proxy :: Proxy n)+ toSing n = case someNatVal n of+ Just (SomeNat (_ :: Proxy n)) -> SomeSing (SNat :: Sing n)+ Nothing -> error "Negative singleton nat"++data instance Sing (n :: Symbol) = KnownSymbol n => SSym++instance KnownSymbol n => SingI n where+ sing = SSym++instance SingKind ('KProxy :: KProxy Symbol) where+ type DemoteRep ('KProxy :: KProxy Symbol) = String+ fromSing (SSym :: Sing n) = symbolVal (Proxy :: Proxy n)+ toSing s = case someSymbolVal s of+ SomeSymbol (_ :: Proxy n) -> SomeSing (SSym :: Sing n)+ +#else++data TLSingInstance (a :: k) where+ TLSingInstance :: TL.SingI a => TLSingInstance a++newtype DI a = Don'tInstantiate (TL.SingI a => TLSingInstance a)++tlSingInstance :: forall (a :: k). TL.Sing a -> TLSingInstance a+tlSingInstance s = with_sing_i TLSingInstance+ where+ with_sing_i :: (TL.SingI a => TLSingInstance a) -> TLSingInstance a+ with_sing_i si = unsafeCoerce (Don'tInstantiate si) s++withTLSingI :: TL.Sing n -> (TL.SingI n => r) -> r+withTLSingI sn r =+ case tlSingInstance sn of+ TLSingInstance -> r++data instance Sing (n :: Nat) = TL.SingRep n Integer => SNat++instance TL.SingRep n Integer => SingI (n :: Nat) where + sing = SNat++instance SingKind ('KProxy :: KProxy Nat) where+ type DemoteRep ('KProxy :: KProxy Nat) = Integer+ fromSing (SNat :: Sing n) = TL.fromSing (TL.sing :: TL.Sing n)+ toSing n+ | n >= 0 = case TL.unsafeSingNat n of+ (tlsing :: TL.Sing n) ->+ withTLSingI tlsing (SomeSing (SNat :: Sing n))+ | otherwise = error "Negative singleton nat"++data instance Sing (n :: Symbol) = TL.SingRep n String => SSym++instance TL.SingRep n String => SingI (n :: Symbol) where+ sing = SSym++instance SingKind ('KProxy :: KProxy Symbol) where+ type DemoteRep ('KProxy :: KProxy Symbol) = String+ fromSing (SSym :: Sing n) = TL.fromSing (TL.sing :: TL.Sing n)+ toSing n = case TL.unsafeSingSymbol n of+ (tlsing :: TL.Sing n) ->+ withTLSingI tlsing (SomeSing (SSym :: Sing n))++-- create 7.8-style TypeLits definitions:+class KnownNat (n :: Nat) where+ natVal :: proxy n -> Integer++class KnownSymbol (n :: Symbol) where+ symbolVal :: proxy n -> String++instance TL.SingI n => KnownNat n where+ natVal _ = TL.fromSing (TL.sing :: TL.Sing n)++instance TL.SingI n => KnownSymbol n where+ symbolVal _ = TL.fromSing (TL.sing :: TL.Sing n)++#endif++-- SDecide instances:+instance SDecide ('KProxy :: KProxy Nat) where+ (SNat :: Sing n) %~ (SNat :: Sing m)+ | natVal (Proxy :: Proxy n) == natVal (Proxy :: Proxy m)+ = Proved $ unsafeCoerce Refl+ | otherwise+ = Disproved (\_ -> error errStr)+ where errStr = "Broken Nat singletons"++instance SDecide ('KProxy :: KProxy Symbol) where+ (SSym :: Sing n) %~ (SSym :: Sing m)+ | symbolVal (Proxy :: Proxy n) == symbolVal (Proxy :: Proxy m)+ = Proved $ unsafeCoerce Refl+ | otherwise+ = Disproved (\_ -> error errStr)+ where errStr = "Broken Symbol singletons"+ +-- need SEq instances for TypeLits kinds+instance SEq ('KProxy :: KProxy Nat) where+ a %:== b+ | fromSing a == fromSing b = unsafeCoerce STrue+ | otherwise = unsafeCoerce SFalse++instance SEq ('KProxy :: KProxy Symbol) where+ a %:== b+ | fromSing a == fromSing b = unsafeCoerce STrue+ | otherwise = unsafeCoerce SFalse+ +-- | Kind-restricted synonym for 'Sing' for @Nat@s+type SNat (x :: Nat) = Sing x++-- | Kind-restricted synonym for 'Sing' for @Symbol@s+type SSymbol (x :: Symbol) = Sing x++-- Convenience functions++-- | Given a singleton for @Nat@, call something requiring a+-- @KnownNat@ instance.+withKnownNat :: Sing n -> (KnownNat n => r) -> r+withKnownNat SNat f = f++-- | Given a singleton for @Symbol@, call something requiring+-- a @KnownSymbol@ instance.+withKnownSymbol :: Sing n -> (KnownSymbol n => r) -> r+withKnownSymbol SSym f = f++-- | The promotion of 'error'+type family Error (str :: Symbol) :: k++-- | The singleton for 'error'+sError :: Sing (str :: Symbol) -> a+sError sstr = error (fromSing sstr)
+ src/Data/Singletons/TypeRepStar.hs view
@@ -0,0 +1,99 @@+{-# LANGUAGE RankNTypes, TypeFamilies, KindSignatures, FlexibleInstances,+ GADTs, UndecidableInstances, ScopedTypeVariables, DataKinds,+ MagicHash, CPP, TypeOperators #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}++-----------------------------------------------------------------------------+-- |+-- Module : Data.Singletons.TypeRepStar+-- Copyright : (C) 2013 Richard Eisenberg+-- License : BSD-style (see LICENSE)+-- Maintainer : Richard Eisenberg (eir@cis.upenn.edu)+-- Stability : experimental+-- Portability : non-portable+--+-- This module defines singleton instances making 'Typeable' the singleton for+-- the kind @*@. The definitions don't fully line up with what is expected+-- within the singletons library, so expect unusual results!+--+----------------------------------------------------------------------------++module Data.Singletons.TypeRepStar (+ Sing(STypeRep)+ -- | Here is the definition of the singleton for @*@:+ --+ -- > data instance Sing (a :: *) where+ -- > STypeRep :: Typeable a => Sing a+ --+ -- Instances for 'SingI', 'SingKind', 'SEq', 'SDecide', and 'TestCoercion' are+ -- also supplied.+ ) where++import Data.Singletons.Instances+import Data.Singletons+import Data.Singletons.Types+import Data.Singletons.Eq+import Data.Typeable+import Unsafe.Coerce+import Data.Singletons.Decide++#if __GLASGOW_HASKELL__ >= 707+import GHC.Exts ( Proxy# )+import Data.Type.Coercion+#else++eqT :: (Typeable a, Typeable b) => Maybe (a :~: b)+eqT = gcast Refl++type instance (a :: *) :== (a :: *) = True++#endif++data instance Sing (a :: *) where+ STypeRep :: Typeable a => Sing a++instance Typeable a => SingI (a :: *) where+ sing = STypeRep+instance SingKind ('KProxy :: KProxy *) where+ type DemoteRep ('KProxy :: KProxy *) = TypeRep+ fromSing (STypeRep :: Sing a) = typeOf (undefined :: a)+ toSing = dirty_mk_STypeRep++instance SEq ('KProxy :: KProxy *) where+ (STypeRep :: Sing a) %:== (STypeRep :: Sing b) =+ case (eqT :: Maybe (a :~: b)) of+ Just Refl -> STrue+ Nothing -> unsafeCoerce SFalse+ -- the Data.Typeable interface isn't strong enough+ -- to enable us to define this without unsafeCoerce++instance SDecide ('KProxy :: KProxy *) where+ (STypeRep :: Sing a) %~ (STypeRep :: Sing b) =+ case (eqT :: Maybe (a :~: b)) of+ Just Refl -> Proved Refl+ Nothing -> Disproved (\Refl -> error "Data.Typeable.eqT failed")++#if __GLASGOW_HASKELL__ >= 707+-- TestEquality instance already defined, but we need this one:+instance TestCoercion Sing where+ testCoercion (STypeRep :: Sing a) (STypeRep :: Sing b) =+ case (eqT :: Maybe (a :~: b)) of+ Just Refl -> Just Coercion+ Nothing -> Nothing+#endif++-- everything below here is private and dirty. Don't look!++newtype DI = Don'tInstantiate (Typeable a => Sing a)+dirty_mk_STypeRep :: TypeRep -> SomeSing ('KProxy :: KProxy *)+dirty_mk_STypeRep rep =+#if __GLASGOW_HASKELL__ >= 707+ let justLikeTypeable :: Proxy# a -> TypeRep+ justLikeTypeable _ = rep+ in+#else+ let justLikeTypeable :: a -> TypeRep+ justLikeTypeable _ = rep+ in+#endif+ unsafeCoerce (Don'tInstantiate STypeRep) justLikeTypeable
+ src/Data/Singletons/Types.hs view
@@ -0,0 +1,64 @@+{-# LANGUAGE PolyKinds, TypeOperators, GADTs, RankNTypes, TypeFamilies,+ CPP, DataKinds #-}++-----------------------------------------------------------------------------+-- |+-- Module : Data.Singletons.Types+-- Copyright : (C) 2013 Richard Eisenberg+-- License : BSD-style (see LICENSE)+-- Maintainer : Richard Eisenberg (eir@cis.upenn.edu)+-- Stability : experimental+-- Portability : non-portable+--+-- Defines and exports types that are useful when working with singletons.+-- Some of these are re-exports from @Data.Type.Equality@.+--+----------------------------------------------------------------------------+++module Data.Singletons.Types (+ KProxy(..), Proxy(..),+ (:~:)(..), gcastWith, TestEquality(..),+ Not, If, type (==), (:==)+ ) where++#if __GLASGOW_HASKELL__ < 707++-- now in Data.Proxy+data KProxy (a :: *) = KProxy+data Proxy a = Proxy++-- now in Data.Type.Equality+data a :~: b where+ Refl :: a :~: a++gcastWith :: (a :~: b) -> ((a ~ b) => r) -> r+gcastWith Refl x = x++class TestEquality (f :: k -> *) where+ testEquality :: f a -> f b -> Maybe (a :~: b)++-- now in Data.Type.Bool+-- | Type-level "If". @If True a b@ ==> @a@; @If False a b@ ==> @b@+type family If (a :: Bool) (b :: k) (c :: k) :: k+type instance If 'True b c = b+type instance If 'False b c = c++type family (a :: k) :== (b :: k) :: Bool+type a == b = a :== b++type family Not (b :: Bool) :: Bool+type instance Not True = False+type instance Not False = True++#else++import Data.Proxy+import Data.Type.Equality+import Data.Type.Bool++-- | A re-export of the type-level @(==)@ that conforms to the singletons naming+-- convention.+type a :== b = a == b++#endif
+ src/Data/Singletons/Util.hs view
@@ -0,0 +1,267 @@+{- Data/Singletons/Util.hs++(c) Richard Eisenberg 2013+eir@cis.upenn.edu++This file contains helper functions internal to the singletons package.+Users of the package should not need to consult this file.+-}++{-# LANGUAGE CPP, TypeSynonymInstances, FlexibleInstances, RankNTypes,+ TemplateHaskell, GeneralizedNewtypeDeriving,+ MultiParamTypeClasses #-}++module Data.Singletons.Util (+ module Data.Singletons.Util,+ module Language.Haskell.TH.Desugar )+ where++import Prelude hiding ( exp )+import Language.Haskell.TH hiding ( Q )+import Language.Haskell.TH.Syntax ( Quasi(..) )+import Language.Haskell.TH.Desugar ( reifyWithWarning, getDataD )+import Data.Char+import Control.Monad+import Control.Applicative+import Control.Monad.Writer+import qualified Data.Map as Map++mkTyFamInst :: Name -> [Type] -> Type -> Dec+mkTyFamInst name lhs rhs =+#if __GLASGOW_HASKELL__ >= 707+ TySynInstD name (TySynEqn lhs rhs)+#else+ TySynInstD name lhs rhs+#endif++-- The list of types that singletons processes by default+basicTypes :: [Name]+basicTypes = [ ''Bool+ , ''Maybe+ , ''Either+ , ''Ordering+ , ''[]+ , ''()+ , ''(,)+ , ''(,,)+ , ''(,,,)+ , ''(,,,,)+ , ''(,,,,,)+ , ''(,,,,,,)+ ]++-- like newName, but even more unique (unique across different splices)+-- TH doesn't allow "newName"s to work at the top-level, so we have to+-- do this trick to ensure the Extract functions are unique+newUniqueName :: Quasi q => String -> q Name+newUniqueName str = do+ n <- qNewName str+ return $ mkName $ show n++-- like reportWarning, but generalized to any Quasi+qReportWarning :: Quasi q => String -> q ()+qReportWarning = qReport False++-- like reportError, but generalized to any Quasi+qReportError :: Quasi q => String -> q ()+qReportError = qReport True++-- extract the degree of a tuple+tupleDegree_maybe :: String -> Maybe Int+tupleDegree_maybe s = do+ '(' : s1 <- return s+ (commas, ")") <- return $ span (== ',') s1+ let degree+ | "" <- commas = 0+ | otherwise = length commas + 1+ return degree++-- extract the degree of a tuple name+tupleNameDegree_maybe :: Name -> Maybe Int+tupleNameDegree_maybe = tupleDegree_maybe . nameBase++-- reduce the four cases of a 'Con' to just two: monomorphic and polymorphic+-- and convert 'StrictType' to 'Type'+ctorCases :: (Name -> [Type] -> a) -> ([TyVarBndr] -> Cxt -> Con -> a) -> Con -> a+ctorCases genFun forallFun ctor = case ctor of+ NormalC name stypes -> genFun name (map snd stypes)+ RecC name vstypes -> genFun name (map (\(_,_,ty) -> ty) vstypes)+ InfixC (_,ty1) name (_,ty2) -> genFun name [ty1, ty2]+ ForallC [] [] ctor' -> ctorCases genFun forallFun ctor'+ ForallC tvbs cx ctor' -> forallFun tvbs cx ctor'++-- reduce the four cases of a 'Con' to just 1: a polymorphic Con is treated+-- as a monomorphic one+ctor1Case :: (Name -> [Type] -> a) -> Con -> a+ctor1Case mono = ctorCases mono (\_ _ ctor -> ctor1Case mono ctor)++-- extract the name and number of arguments to a constructor+extractNameArgs :: Con -> (Name, Int)+extractNameArgs = ctor1Case (\name tys -> (name, length tys))++-- reinterpret a name. This is useful when a Name has an associated+-- namespace that we wish to forget+reinterpret :: Name -> Name+reinterpret = mkName . nameBase++-- is an identifier uppercase?+isUpcase :: Name -> Bool+isUpcase n = let first = head (nameBase n) in isUpper first || first == ':'++-- make an identifier uppercase+upcase :: Name -> Name+upcase n =+ let str = nameBase n+ first = head str in+ if isLetter first+ then mkName ((toUpper first) : tail str)+ else mkName (':' : str)++-- make an identifier lowercase+locase :: Name -> Name+locase n =+ let str = nameBase n+ first = head str in+ if isLetter first+ then mkName ((toLower first) : tail str)+ else mkName (tail str) -- remove the ":"++-- put an uppercase prefix on a name. Takes two prefixes: one for identifiers+-- and one for symbols+prefixUCName :: String -> String -> Name -> Name+prefixUCName pre tyPre n = case (nameBase n) of+ (':' : rest) -> mkName (tyPre ++ rest)+ alpha -> mkName (pre ++ alpha)++-- put a lowercase prefix on a name. Takes two prefixes: one for identifiers+-- and one for symbols+prefixLCName :: String -> String -> Name -> Name+prefixLCName pre tyPre n =+ let str = nameBase n+ first = head str in+ if isLetter first+ then mkName (pre ++ str)+ else mkName (tyPre ++ str)++-- extract the kind from a TyVarBndr. Returns '*' by default.+extractTvbKind :: TyVarBndr -> Kind+extractTvbKind (PlainTV _) = StarT -- FIXME: This seems wrong.+extractTvbKind (KindedTV _ k) = k++-- extract the name from a TyVarBndr.+extractTvbName :: TyVarBndr -> Name+extractTvbName (PlainTV n) = n+extractTvbName (KindedTV n _) = n++-- apply a type to a list of types+foldType :: Type -> [Type] -> Type+foldType = foldl AppT++-- apply an expression to a list of expressions+foldExp :: Exp -> [Exp] -> Exp+foldExp = foldl AppE++-- is a kind a variable?+isVarK :: Kind -> Bool+isVarK (VarT _) = True+isVarK _ = False++-- tuple up a list of expressions+mkTupleExp :: [Exp] -> Exp+mkTupleExp [x] = x+mkTupleExp xs = TupE xs++-- tuple up a list of patterns+mkTuplePat :: [Pat] -> Pat+mkTuplePat [x] = x+mkTuplePat xs = TupP xs++-- choose the first non-empty list+orIfEmpty :: [a] -> [a] -> [a]+orIfEmpty [] x = x+orIfEmpty x _ = x++-- an empty list of matches, compatible with GHC 7.6.3+emptyMatches :: [Match]+emptyMatches = [Match WildP (NormalB (AppE (VarE 'error) (LitE (StringL errStr)))) []]+ where errStr = "Empty case reached -- this should be impossible"++-- build a pattern match over several expressions, each with only one pattern+multiCase :: [Exp] -> [Pat] -> Exp -> Exp+multiCase [] [] body = body+multiCase scruts pats body =+ CaseE (mkTupleExp scruts)+ [Match (mkTuplePat pats) (NormalB body) []]++-- a monad transformer for writing a monoid alongside returning a Q+newtype QWithAux m q a = QWA { runQWA :: WriterT m q a }+ deriving (Functor, Applicative, Monad, MonadTrans)++instance (Monoid m, Monad q) => MonadWriter m (QWithAux m q) where+ writer = QWA . writer+ tell = QWA . tell+ listen = QWA . listen . runQWA+ pass = QWA . pass . runQWA++-- make a Quasi instance for easy lifting+instance (Quasi q, Monoid m) => Quasi (QWithAux m q) where+ qNewName = lift `comp1` qNewName+ qReport = lift `comp2` qReport+ qLookupName = lift `comp2` qLookupName+ qReify = lift `comp1` qReify+ qReifyInstances = lift `comp2` qReifyInstances+ qLocation = lift qLocation+ qRunIO = lift `comp1` qRunIO+ qAddDependentFile = lift `comp1` qAddDependentFile+#if __GLASGOW_HASKELL__ >= 707+ qReifyRoles = lift `comp1` qReifyRoles+ qReifyAnnotations = lift `comp1` qReifyAnnotations+ qReifyModule = lift `comp1` qReifyModule+ qAddTopDecls = lift `comp1` qAddTopDecls+ qAddModFinalizer = lift `comp1` qAddModFinalizer+ qGetQ = lift qGetQ+ qPutQ = lift `comp1` qPutQ+#endif++ qRecover exp handler = do+ (result, aux) <- lift $ qRecover (evalForPair exp) (evalForPair handler)+ tell aux+ return result++-- helper functions for composition+comp1 :: (b -> c) -> (a -> b) -> a -> c+comp1 = (.)++comp2 :: (c -> d) -> (a -> b -> c) -> a -> b -> d+comp2 f g a b = f (g a b)++-- run a computation with an auxiliary monoid, discarding the monoid result+evalWithoutAux :: Quasi q => QWithAux m q a -> q a+evalWithoutAux = liftM fst . runWriterT . runQWA++-- run a computation with an auxiliary monoid, returning only the monoid result+evalForAux :: Quasi q => QWithAux m q a -> q m+evalForAux = execWriterT . runQWA++-- run a computation with an auxiliary monoid, return both the result+-- of the computation and the monoid result+evalForPair :: Quasi q => QWithAux m q a -> q (a, m)+evalForPair = runWriterT . runQWA++-- in a computation with an auxiliary map, add a binding to the map+addBinding :: (Quasi q, Ord k) => k -> v -> QWithAux (Map.Map k v) q ()+addBinding k v = tell (Map.singleton k v)++-- in a computation with an auxiliar list, add an element to the list+addElement :: Quasi q => elt -> QWithAux [elt] q ()+addElement elt = tell [elt]++-- lift concatMap into a monad+concatMapM :: Monad m => (a -> m [b]) -> [a] -> m [b]+concatMapM fn list = do+ bss <- mapM fn list+ return $ concat bss++-- make a one-element list+listify :: a -> [a]+listify = return
+ src/Data/Singletons/Void.hs view
@@ -0,0 +1,78 @@+{- Data/Singletons/Void.hs++ A reimplementation of a Void type, copied shamelessly from Edward Kmett's void+ package, but without inducing a dependency.++-}++{-# LANGUAGE CPP, Trustworthy, DeriveDataTypeable, DeriveGeneric, StandaloneDeriving #-}++-----------------------------------------------------------------------------+-- |+-- Copyright : (C) 2008-2013 Edward Kmett+-- License : BSD-style (see LICENSE)+-- Maintainer : Richard Eisenberg (eir@cis.upenn.edu)+-- Stability : experimental+-- Portability : non-portable+--+-- This module is a reimplementation of Edward Kmett's @void@ package.+-- It is included within singletons to avoid depending on @void@ and all the+-- packages that depends on (including @text@). If this causes problems for+-- you (that singletons has its own 'Void' type), please let me (Richard Eisenberg)+-- know at @eir@ at @cis.upenn.edu@.+--+----------------------------------------------------------------------------+module Data.Singletons.Void+ ( Void+ , absurd+ , vacuous+ , vacuousM+ ) where++import Control.Monad (liftM)+import Data.Ix+import Data.Data+import GHC.Generics+import Control.Exception++-- | A logically uninhabited data type.+newtype Void = Void Void+ deriving (Data, Typeable, Generic)++instance Eq Void where+ _ == _ = True++instance Ord Void where+ compare _ _ = EQ++instance Show Void where+ showsPrec _ = absurd++-- | Reading a 'Void' value is always a parse error, considering 'Void' as+-- a data type with no constructors.+instance Read Void where+ readsPrec _ _ = []++-- | Since 'Void' values logically don't exist, this witnesses the logical+-- reasoning tool of \"ex falso quodlibet\".+absurd :: Void -> a+absurd a = a `seq` spin a where+ spin (Void b) = spin b++-- | If 'Void' is uninhabited then any 'Functor' that holds only values of type 'Void'+-- is holding no values.+vacuous :: Functor f => f Void -> f a+vacuous = fmap absurd++-- | If 'Void' is uninhabited then any 'Monad' that holds values of type 'Void'+-- is holding no values.+vacuousM :: Monad m => m Void -> m a+vacuousM = liftM absurd++instance Ix Void where+ range _ = []+ index _ = absurd+ inRange _ = absurd+ rangeSize _ = 0++instance Exception Void
+ tests/SingletonsTestSuite.hs view
@@ -0,0 +1,41 @@+module Main (+ main+ ) where++import Test.Tasty ( TestTree, defaultMain, testGroup )+import SingletonsTestSuiteUtils ( compileAndDumpStdTest, compileAndDumpTest+ , testCompileAndDumpGroup, ghcOpts )++main :: IO ()+main = defaultMain tests++tests :: TestTree+tests =+ testGroup "Testsuite" $ [+ testCompileAndDumpGroup "Singletons"+ [ compileAndDumpStdTest "Nat"+ , compileAndDumpStdTest "Empty"+ , compileAndDumpStdTest "Maybe"+ , compileAndDumpStdTest "BoxUnBox"+ , compileAndDumpStdTest "Operators"+ , compileAndDumpStdTest "BadPlus"+ , compileAndDumpStdTest "HigherOrder"+ , compileAndDumpStdTest "Contains"+ , compileAndDumpStdTest "AtPattern"+ , compileAndDumpStdTest "DataValues"+ , compileAndDumpStdTest "EqInstances"+ , compileAndDumpStdTest "Star"+ ],+ testCompileAndDumpGroup "Promote"+ [ compileAndDumpStdTest "PatternMatching"+ , compileAndDumpStdTest "NumArgs" -- remove once we have eta-expansion+ ],+ testGroup "Database client"+ [ compileAndDumpTest "GradingClient/Database" ghcOpts+ , compileAndDumpTest "GradingClient/Main" ghcOpts+ ],+ testCompileAndDumpGroup "InsertionSort"+ [ compileAndDumpStdTest "InsertionSortImp"+ ]+ ]+
+ tests/SingletonsTestSuiteUtils.hs view
@@ -0,0 +1,233 @@+{-# LANGUAGE CPP, DeriveDataTypeable #-}+module SingletonsTestSuiteUtils (+ compileAndDumpTest+ , compileAndDumpStdTest+ , testCompileAndDumpGroup+ , ghcOpts+ , singletonsVersion+ ) where++import Control.Exception ( Exception, throw )+import Data.List ( intercalate )+import Data.Typeable ( Typeable )+import System.Exit ( ExitCode(..) )+import System.FilePath ( takeBaseName, pathSeparator )+import System.IO ( IOMode(..), hGetContents, openFile )+import System.Process ( CreateProcess(..), StdStream(..)+ , createProcess, proc, waitForProcess )+import Test.Tasty ( TestTree, testGroup )+import Test.Tasty.Golden ( goldenVsFileDiff )++import Distribution.PackageDescription.Parse ( readPackageDescription )+import Distribution.PackageDescription.Configuration ( flattenPackageDescription )+import Distribution.PackageDescription ( PackageDescription(..) )+import Distribution.Verbosity ( silent )+import Distribution.Package ( PackageIdentifier(..) )+import Data.Version ( showVersion )+import System.IO.Unsafe ( unsafePerformIO )++-- Some infractructure for handling external process errors+data ProcessException = ProcessException String deriving (Typeable)++instance Exception ProcessException++instance Show ProcessException where+ show (ProcessException msg) = msg++-- GHC executable name (if on path) or full path+ghcPath :: FilePath+ghcPath = "ghc"++-- directory storing compile-and-run tests and golden files+goldenPath :: FilePath+goldenPath = "tests/compile-and-dump/"++-- path containing compiled *.hi files. Relative to goldenPath.+-- See Note [-package-name hack]+includePath :: FilePath+includePath = "../../dist/build"++ghcVersion :: String+#if __GLASGOW_HASKELL__ < 706+ghcVersion = error "testsuite requires GHC 7.6 or newer"+#else+#if __GLASGOW_HASKELL__ >= 706 && __GLASGOW_HASKELL__ < 707+ghcVersion = ".ghc76"+#else+ghcVersion = ".ghc78"+#endif+#endif++-- the version number of "singletons"+singletonsVersion :: String+singletonsVersion = unsafePerformIO $ do+ gpd <- readPackageDescription silent "singletons.cabal"+ let pd = flattenPackageDescription gpd+ return $ showVersion $ pkgVersion $ package pd++-- GHC options used when running the tests+ghcOpts :: [String]+ghcOpts = [+ "-v0"+ , "-c"+ , "-package-name singletons-" ++ singletonsVersion -- See Note [-package-name hack]+ , "-ddump-splices"+ , "-dsuppress-uniques"+ , "-fforce-recomp"+ , "-i" ++ includePath+ , "-XTemplateHaskell"+ , "-XDataKinds"+ , "-XKindSignatures"+ , "-XTypeFamilies"+ , "-XTemplateHaskell"+ , "-XTypeOperators"+ , "-XKindSignatures"+ , "-XDataKinds"+ , "-XMultiParamTypeClasses"+ , "-XGADTs"+ , "-XTypeFamilies"+ , "-XFlexibleInstances"+ , "-XUndecidableInstances"+ , "-XRankNTypes"+ , "-XScopedTypeVariables"+ , "-XPolyKinds"+ , "-XFlexibleContexts"+ , "-XIncoherentInstances"+ , "-XCPP"+ ]++-- Note [-package-name hack]+-- ~~~~~~~~~~~~~~~~~~~~~~~~~+--+-- We want to avoid installing singletons package before running the+-- testsuite, because in this way we prevent double compilation of the+-- library. To do this we pass -package-name option to GHC to convince+-- it that the test files are actually part of the current+-- package. This means that library doesn't have to be installed+-- globally and interface files generated during library compilation+-- can be used when compiling test cases. We use "-i" option to point+-- GHC to directory containing compiled interface files.++-- Compile a test using specified GHC options. Save output to file, filter with+-- sed and compare it with golden file. This function also builds golden file+-- from a template file. Putting it here is a bit of a hack but it's easy and it+-- works.+--+-- First parameter is a path to the test file relative to goldenPath directory+-- with no ".hs".+compileAndDumpTest :: FilePath -> [String] -> TestTree+compileAndDumpTest testName opts =+ goldenVsFileDiff+ (takeBaseName testName)+ (\ref new -> ["diff", "-w", "-B", ref, new]) -- see Note [Diff options]+ goldenFilePath+ actualFilePath+ compileWithGHC+ where+ testPath = testName ++ ".hs"+ templateFilePath = goldenPath ++ testName ++ ghcVersion ++ ".template"+ goldenFilePath = goldenPath ++ testName ++ ".golden"+ actualFilePath = goldenPath ++ testName ++ ".actual"++ compileWithGHC :: IO ()+ compileWithGHC = do+ hActualFile <- openFile actualFilePath WriteMode+ (_, _, _, pid) <- createProcess (proc ghcPath (testPath : opts))+ { std_out = UseHandle hActualFile+ , std_err = UseHandle hActualFile+ , cwd = Just goldenPath }+ _ <- waitForProcess pid -- see Note [Ignore exit code]+ filterWithSed actualFilePath -- see Note [Normalization with sed]+ buildGoldenFile templateFilePath goldenFilePath+ return ()++-- Compile-and-dump test using standard GHC options defined by the testsuite.+-- It takes two parameters: name of a file containing a test (no ".hs"+-- extension) and directory where the test is located (relative to+-- goldenPath). Test name and path are passed separately so that this function+-- can be used easily with testCompileAndDumpGroup.+compileAndDumpStdTest :: FilePath -> FilePath -> TestTree+compileAndDumpStdTest testName testPath =+ compileAndDumpTest (testPath ++ (pathSeparator : testName)) ghcOpts++-- A convenience function for defining a group of compile-and-dump tests stored+-- in the same subdirectory. It takes the name of subdirectory and list of+-- functions that given the name of subdirectory create a TestTree. Designed for+-- use with compileAndDumpStdTest.+testCompileAndDumpGroup :: FilePath -> [FilePath -> TestTree] -> TestTree+testCompileAndDumpGroup testDir tests =+ testGroup testDir $ map ($ testDir) tests++-- Note [Ignore exit code]+-- ~~~~~~~~~~~~~~~~~~~~~~~+--+-- It may happen that compilation of a source file fails. We could find out+-- whether that happened by inspecting the exit code of GHC process. But it+-- would be tricky to get a helpful message from the failing test: we would need+-- to display stderr which we just wrote into a file. Luckliy we don't have to+-- do that - we can ignore the problem here and let the test fail when the+-- actual file is compared with the golden file.++-- Note [Diff options]+-- ~~~~~~~~~~~~~~~~~~~+--+-- We use following diff options:+-- -w - Ignore all white space.+-- -B - Ignore changes whose lines are all blank.++-- Note [Normalization with sed]+-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+--+-- Output file is normalized with sed. Line numbers generated in splices:+--+-- Foo:(40,3)-(42,4)+-- Foo.hs:7:3:+-- Equals_1235967303+--+-- are turned into:+--+-- Foo:(0,0)-(0,0)+-- Foo.hs:0:0:+-- Equals_0123456789+--+-- This allows to insert comments into test file without the need to modify the+-- golden file to adjust line numbers.+--+-- Note that GNU sed (on Linux) and BSD sed (on MacOS) are slightly different.+-- We use conditional compilation to deal with this.++filterWithSed :: FilePath -> IO ()+filterWithSed file = runProcessWithOpts CreatePipe "sed"+#ifdef darwin_HOST_OS+ [ "-i", "''"+#else+ [ "-i"+#endif+ , "-e", "'s/([0-9]*,[0-9]*)-([0-9]*,[0-9]*)/(0,0)-(0,0)/g'"+ , "-e", "'s/:[0-9][0-9]*:[0-9][0-9]*/:0:0/g'"+ , "-e", "'s/:[0-9]*:[0-9]*-[0-9]*/:0:0:/g'"+ , "-e", "'s/[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]/0123456789/g'"+ , file+ ]++buildGoldenFile :: FilePath -> FilePath -> IO ()+buildGoldenFile templateFilePath goldenFilePath = do+ hGoldenFile <- openFile goldenFilePath WriteMode+ runProcessWithOpts (UseHandle hGoldenFile) "awk"+ [ "-f", "tests/compile-and-dump/buildGoldenFiles.awk"+ , templateFilePath+ ]++runProcessWithOpts :: StdStream -> String -> [String] -> IO ()+runProcessWithOpts stdout program opts = do+ (_, _, Just serr, pid) <-+ createProcess (proc "bash" ["-c", (intercalate " " (program : opts))])+ { std_out = stdout+ , std_err = CreatePipe }+ ecode <- waitForProcess pid+ case ecode of+ ExitSuccess -> return ()+ ExitFailure _ -> do+ err <- hGetContents serr -- Text would be faster than String, but this is+ -- a corner case so probably not worth it.+ throw $ ProcessException ("Error when running " ++ program ++ ":\n" ++ err)
+ tests/compile-and-dump/GradingClient/Database.ghc76.template view
@@ -0,0 +1,4470 @@+GradingClient/Database.hs:0:0: Splicing declarations+ singletons+ [d| data Nat+ = Zero | Succ Nat+ deriving (Eq, Ord) |]+ ======>+ GradingClient/Database.hs:(0,0)-(0,0)+ data Nat+ = Zero | Succ Nat+ deriving (Eq, Ord)+ type instance (:==) Zero Zero = True+ type instance (:==) Zero (Succ b) = False+ type instance (:==) (Succ a) Zero = False+ type instance (:==) (Succ a) (Succ b) = :== a b+ data instance Sing (z :: Nat)+ = z ~ Zero => SZero |+ forall (n :: Nat). z ~ Succ n => SSucc (Sing n)+ type SNat (z :: Nat) = Sing z+ instance SingKind (KProxy :: KProxy Nat) where+ type instance DemoteRep (KProxy :: KProxy Nat) = Nat+ fromSing SZero = Zero+ fromSing (SSucc b) = Succ (fromSing b)+ toSing Zero = SomeSing SZero+ toSing (Succ b)+ = case toSing b :: SomeSing (KProxy :: KProxy Nat) of {+ SomeSing c -> SomeSing (SSucc c) }+ instance SEq (KProxy :: KProxy Nat) where+ %:== SZero SZero = STrue+ %:== SZero (SSucc _) = SFalse+ %:== (SSucc _) SZero = SFalse+ %:== (SSucc a) (SSucc b) = (%:==) a b+ instance SDecide (KProxy :: KProxy Nat) where+ %~ SZero SZero = Proved Refl+ %~ SZero (SSucc _)+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ (SSucc _) SZero+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ (SSucc a) (SSucc b)+ = case (%~) a b of {+ Proved Refl -> Proved Refl+ Disproved contra -> Disproved (\ Refl -> contra Refl) }+ instance SingI Zero where+ sing = SZero+ instance SingI n => SingI (Succ (n :: Nat)) where+ sing = SSucc sing+GradingClient/Database.hs:0:0: Splicing declarations+ singletons+ [d| append :: Schema -> Schema -> Schema+ append (Sch s1) (Sch s2) = Sch (s1 ++ s2)+ attrNotIn :: Attribute -> Schema -> Bool+ attrNotIn _ (Sch []) = True+ attrNotIn (Attr name u) (Sch ((Attr name' _) : t))+ = (name /= name') && (attrNotIn (Attr name u) (Sch t))+ disjoint :: Schema -> Schema -> Bool+ disjoint (Sch []) _ = True+ disjoint (Sch (h : t)) s = (attrNotIn h s) && (disjoint (Sch t) s)+ occurs :: [AChar] -> Schema -> Bool+ occurs _ (Sch []) = False+ occurs name (Sch ((Attr name' _) : attrs))+ = name == name' || occurs name (Sch attrs)+ lookup :: [AChar] -> Schema -> U+ lookup _ (Sch []) = undefined+ lookup name (Sch ((Attr name' u) : attrs))+ = if name == name' then u else lookup name (Sch attrs)+ + data U+ = BOOL | STRING | NAT | VEC U Nat+ deriving (Read, Eq, Show)+ data AChar+ = CA |+ CB |+ CC |+ CD |+ CE |+ CF |+ CG |+ CH |+ CI |+ CJ |+ CK |+ CL |+ CM |+ CN |+ CO |+ CP |+ CQ |+ CR |+ CS |+ CT |+ CU |+ CV |+ CW |+ CX |+ CY |+ CZ+ deriving (Read, Show, Eq)+ data Attribute = Attr [AChar] U+ data Schema = Sch [Attribute] |]+ ======>+ GradingClient/Database.hs:(0,0)-(0,0)+ data U+ = BOOL | STRING | NAT | VEC U Nat+ deriving (Read, Eq, Show)+ data AChar+ = CA |+ CB |+ CC |+ CD |+ CE |+ CF |+ CG |+ CH |+ CI |+ CJ |+ CK |+ CL |+ CM |+ CN |+ CO |+ CP |+ CQ |+ CR |+ CS |+ CT |+ CU |+ CV |+ CW |+ CX |+ CY |+ CZ+ deriving (Read, Show, Eq)+ data Attribute = Attr [AChar] U+ data Schema = Sch [Attribute]+ append :: Schema -> Schema -> Schema+ append (Sch s1) (Sch s2) = Sch (s1 ++ s2)+ attrNotIn :: Attribute -> Schema -> Bool+ attrNotIn _ (Sch GHC.Types.[]) = True+ attrNotIn (Attr name u) (Sch ((Attr name' _) GHC.Types.: t))+ = ((name /= name') && (attrNotIn (Attr name u) (Sch t)))+ disjoint :: Schema -> Schema -> Bool+ disjoint (Sch GHC.Types.[]) _ = True+ disjoint (Sch (h GHC.Types.: t)) s+ = ((attrNotIn h s) && (disjoint (Sch t) s))+ occurs :: [AChar] -> Schema -> Bool+ occurs _ (Sch GHC.Types.[]) = False+ occurs name (Sch ((Attr name' _) GHC.Types.: attrs))+ = ((name == name') || (occurs name (Sch attrs)))+ lookup :: [AChar] -> Schema -> U+ lookup _ (Sch GHC.Types.[]) = undefined+ lookup name (Sch ((Attr name' u) GHC.Types.: attrs))+ = if (name == name') then u else lookup name (Sch attrs)+ type instance (:==) BOOL BOOL = True+ type instance (:==) BOOL STRING = False+ type instance (:==) BOOL NAT = False+ type instance (:==) BOOL (VEC b b) = False+ type instance (:==) STRING BOOL = False+ type instance (:==) STRING STRING = True+ type instance (:==) STRING NAT = False+ type instance (:==) STRING (VEC b b) = False+ type instance (:==) NAT BOOL = False+ type instance (:==) NAT STRING = False+ type instance (:==) NAT NAT = True+ type instance (:==) NAT (VEC b b) = False+ type instance (:==) (VEC a a) BOOL = False+ type instance (:==) (VEC a a) STRING = False+ type instance (:==) (VEC a a) NAT = False+ type instance (:==) (VEC a a) (VEC b b) = :&& (:== a b) (:== a b)+ type instance (:==) CA CA = True+ type instance (:==) CA CB = False+ type instance (:==) CA CC = False+ type instance (:==) CA CD = False+ type instance (:==) CA CE = False+ type instance (:==) CA CF = False+ type instance (:==) CA CG = False+ type instance (:==) CA CH = False+ type instance (:==) CA CI = False+ type instance (:==) CA CJ = False+ type instance (:==) CA CK = False+ type instance (:==) CA CL = False+ type instance (:==) CA CM = False+ type instance (:==) CA CN = False+ type instance (:==) CA CO = False+ type instance (:==) CA CP = False+ type instance (:==) CA CQ = False+ type instance (:==) CA CR = False+ type instance (:==) CA CS = False+ type instance (:==) CA CT = False+ type instance (:==) CA CU = False+ type instance (:==) CA CV = False+ type instance (:==) CA CW = False+ type instance (:==) CA CX = False+ type instance (:==) CA CY = False+ type instance (:==) CA CZ = False+ type instance (:==) CB CA = False+ type instance (:==) CB CB = True+ type instance (:==) CB CC = False+ type instance (:==) CB CD = False+ type instance (:==) CB CE = False+ type instance (:==) CB CF = False+ type instance (:==) CB CG = False+ type instance (:==) CB CH = False+ type instance (:==) CB CI = False+ type instance (:==) CB CJ = False+ type instance (:==) CB CK = False+ type instance (:==) CB CL = False+ type instance (:==) CB CM = False+ type instance (:==) CB CN = False+ type instance (:==) CB CO = False+ type instance (:==) CB CP = False+ type instance (:==) CB CQ = False+ type instance (:==) CB CR = False+ type instance (:==) CB CS = False+ type instance (:==) CB CT = False+ type instance (:==) CB CU = False+ type instance (:==) CB CV = False+ type instance (:==) CB CW = False+ type instance (:==) CB CX = False+ type instance (:==) CB CY = False+ type instance (:==) CB CZ = False+ type instance (:==) CC CA = False+ type instance (:==) CC CB = False+ type instance (:==) CC CC = True+ type instance (:==) CC CD = False+ type instance (:==) CC CE = False+ type instance (:==) CC CF = False+ type instance (:==) CC CG = False+ type instance (:==) CC CH = False+ type instance (:==) CC CI = False+ type instance (:==) CC CJ = False+ type instance (:==) CC CK = False+ type instance (:==) CC CL = False+ type instance (:==) CC CM = False+ type instance (:==) CC CN = False+ type instance (:==) CC CO = False+ type instance (:==) CC CP = False+ type instance (:==) CC CQ = False+ type instance (:==) CC CR = False+ type instance (:==) CC CS = False+ type instance (:==) CC CT = False+ type instance (:==) CC CU = False+ type instance (:==) CC CV = False+ type instance (:==) CC CW = False+ type instance (:==) CC CX = False+ type instance (:==) CC CY = False+ type instance (:==) CC CZ = False+ type instance (:==) CD CA = False+ type instance (:==) CD CB = False+ type instance (:==) CD CC = False+ type instance (:==) CD CD = True+ type instance (:==) CD CE = False+ type instance (:==) CD CF = False+ type instance (:==) CD CG = False+ type instance (:==) CD CH = False+ type instance (:==) CD CI = False+ type instance (:==) CD CJ = False+ type instance (:==) CD CK = False+ type instance (:==) CD CL = False+ type instance (:==) CD CM = False+ type instance (:==) CD CN = False+ type instance (:==) CD CO = False+ type instance (:==) CD CP = False+ type instance (:==) CD CQ = False+ type instance (:==) CD CR = False+ type instance (:==) CD CS = False+ type instance (:==) CD CT = False+ type instance (:==) CD CU = False+ type instance (:==) CD CV = False+ type instance (:==) CD CW = False+ type instance (:==) CD CX = False+ type instance (:==) CD CY = False+ type instance (:==) CD CZ = False+ type instance (:==) CE CA = False+ type instance (:==) CE CB = False+ type instance (:==) CE CC = False+ type instance (:==) CE CD = False+ type instance (:==) CE CE = True+ type instance (:==) CE CF = False+ type instance (:==) CE CG = False+ type instance (:==) CE CH = False+ type instance (:==) CE CI = False+ type instance (:==) CE CJ = False+ type instance (:==) CE CK = False+ type instance (:==) CE CL = False+ type instance (:==) CE CM = False+ type instance (:==) CE CN = False+ type instance (:==) CE CO = False+ type instance (:==) CE CP = False+ type instance (:==) CE CQ = False+ type instance (:==) CE CR = False+ type instance (:==) CE CS = False+ type instance (:==) CE CT = False+ type instance (:==) CE CU = False+ type instance (:==) CE CV = False+ type instance (:==) CE CW = False+ type instance (:==) CE CX = False+ type instance (:==) CE CY = False+ type instance (:==) CE CZ = False+ type instance (:==) CF CA = False+ type instance (:==) CF CB = False+ type instance (:==) CF CC = False+ type instance (:==) CF CD = False+ type instance (:==) CF CE = False+ type instance (:==) CF CF = True+ type instance (:==) CF CG = False+ type instance (:==) CF CH = False+ type instance (:==) CF CI = False+ type instance (:==) CF CJ = False+ type instance (:==) CF CK = False+ type instance (:==) CF CL = False+ type instance (:==) CF CM = False+ type instance (:==) CF CN = False+ type instance (:==) CF CO = False+ type instance (:==) CF CP = False+ type instance (:==) CF CQ = False+ type instance (:==) CF CR = False+ type instance (:==) CF CS = False+ type instance (:==) CF CT = False+ type instance (:==) CF CU = False+ type instance (:==) CF CV = False+ type instance (:==) CF CW = False+ type instance (:==) CF CX = False+ type instance (:==) CF CY = False+ type instance (:==) CF CZ = False+ type instance (:==) CG CA = False+ type instance (:==) CG CB = False+ type instance (:==) CG CC = False+ type instance (:==) CG CD = False+ type instance (:==) CG CE = False+ type instance (:==) CG CF = False+ type instance (:==) CG CG = True+ type instance (:==) CG CH = False+ type instance (:==) CG CI = False+ type instance (:==) CG CJ = False+ type instance (:==) CG CK = False+ type instance (:==) CG CL = False+ type instance (:==) CG CM = False+ type instance (:==) CG CN = False+ type instance (:==) CG CO = False+ type instance (:==) CG CP = False+ type instance (:==) CG CQ = False+ type instance (:==) CG CR = False+ type instance (:==) CG CS = False+ type instance (:==) CG CT = False+ type instance (:==) CG CU = False+ type instance (:==) CG CV = False+ type instance (:==) CG CW = False+ type instance (:==) CG CX = False+ type instance (:==) CG CY = False+ type instance (:==) CG CZ = False+ type instance (:==) CH CA = False+ type instance (:==) CH CB = False+ type instance (:==) CH CC = False+ type instance (:==) CH CD = False+ type instance (:==) CH CE = False+ type instance (:==) CH CF = False+ type instance (:==) CH CG = False+ type instance (:==) CH CH = True+ type instance (:==) CH CI = False+ type instance (:==) CH CJ = False+ type instance (:==) CH CK = False+ type instance (:==) CH CL = False+ type instance (:==) CH CM = False+ type instance (:==) CH CN = False+ type instance (:==) CH CO = False+ type instance (:==) CH CP = False+ type instance (:==) CH CQ = False+ type instance (:==) CH CR = False+ type instance (:==) CH CS = False+ type instance (:==) CH CT = False+ type instance (:==) CH CU = False+ type instance (:==) CH CV = False+ type instance (:==) CH CW = False+ type instance (:==) CH CX = False+ type instance (:==) CH CY = False+ type instance (:==) CH CZ = False+ type instance (:==) CI CA = False+ type instance (:==) CI CB = False+ type instance (:==) CI CC = False+ type instance (:==) CI CD = False+ type instance (:==) CI CE = False+ type instance (:==) CI CF = False+ type instance (:==) CI CG = False+ type instance (:==) CI CH = False+ type instance (:==) CI CI = True+ type instance (:==) CI CJ = False+ type instance (:==) CI CK = False+ type instance (:==) CI CL = False+ type instance (:==) CI CM = False+ type instance (:==) CI CN = False+ type instance (:==) CI CO = False+ type instance (:==) CI CP = False+ type instance (:==) CI CQ = False+ type instance (:==) CI CR = False+ type instance (:==) CI CS = False+ type instance (:==) CI CT = False+ type instance (:==) CI CU = False+ type instance (:==) CI CV = False+ type instance (:==) CI CW = False+ type instance (:==) CI CX = False+ type instance (:==) CI CY = False+ type instance (:==) CI CZ = False+ type instance (:==) CJ CA = False+ type instance (:==) CJ CB = False+ type instance (:==) CJ CC = False+ type instance (:==) CJ CD = False+ type instance (:==) CJ CE = False+ type instance (:==) CJ CF = False+ type instance (:==) CJ CG = False+ type instance (:==) CJ CH = False+ type instance (:==) CJ CI = False+ type instance (:==) CJ CJ = True+ type instance (:==) CJ CK = False+ type instance (:==) CJ CL = False+ type instance (:==) CJ CM = False+ type instance (:==) CJ CN = False+ type instance (:==) CJ CO = False+ type instance (:==) CJ CP = False+ type instance (:==) CJ CQ = False+ type instance (:==) CJ CR = False+ type instance (:==) CJ CS = False+ type instance (:==) CJ CT = False+ type instance (:==) CJ CU = False+ type instance (:==) CJ CV = False+ type instance (:==) CJ CW = False+ type instance (:==) CJ CX = False+ type instance (:==) CJ CY = False+ type instance (:==) CJ CZ = False+ type instance (:==) CK CA = False+ type instance (:==) CK CB = False+ type instance (:==) CK CC = False+ type instance (:==) CK CD = False+ type instance (:==) CK CE = False+ type instance (:==) CK CF = False+ type instance (:==) CK CG = False+ type instance (:==) CK CH = False+ type instance (:==) CK CI = False+ type instance (:==) CK CJ = False+ type instance (:==) CK CK = True+ type instance (:==) CK CL = False+ type instance (:==) CK CM = False+ type instance (:==) CK CN = False+ type instance (:==) CK CO = False+ type instance (:==) CK CP = False+ type instance (:==) CK CQ = False+ type instance (:==) CK CR = False+ type instance (:==) CK CS = False+ type instance (:==) CK CT = False+ type instance (:==) CK CU = False+ type instance (:==) CK CV = False+ type instance (:==) CK CW = False+ type instance (:==) CK CX = False+ type instance (:==) CK CY = False+ type instance (:==) CK CZ = False+ type instance (:==) CL CA = False+ type instance (:==) CL CB = False+ type instance (:==) CL CC = False+ type instance (:==) CL CD = False+ type instance (:==) CL CE = False+ type instance (:==) CL CF = False+ type instance (:==) CL CG = False+ type instance (:==) CL CH = False+ type instance (:==) CL CI = False+ type instance (:==) CL CJ = False+ type instance (:==) CL CK = False+ type instance (:==) CL CL = True+ type instance (:==) CL CM = False+ type instance (:==) CL CN = False+ type instance (:==) CL CO = False+ type instance (:==) CL CP = False+ type instance (:==) CL CQ = False+ type instance (:==) CL CR = False+ type instance (:==) CL CS = False+ type instance (:==) CL CT = False+ type instance (:==) CL CU = False+ type instance (:==) CL CV = False+ type instance (:==) CL CW = False+ type instance (:==) CL CX = False+ type instance (:==) CL CY = False+ type instance (:==) CL CZ = False+ type instance (:==) CM CA = False+ type instance (:==) CM CB = False+ type instance (:==) CM CC = False+ type instance (:==) CM CD = False+ type instance (:==) CM CE = False+ type instance (:==) CM CF = False+ type instance (:==) CM CG = False+ type instance (:==) CM CH = False+ type instance (:==) CM CI = False+ type instance (:==) CM CJ = False+ type instance (:==) CM CK = False+ type instance (:==) CM CL = False+ type instance (:==) CM CM = True+ type instance (:==) CM CN = False+ type instance (:==) CM CO = False+ type instance (:==) CM CP = False+ type instance (:==) CM CQ = False+ type instance (:==) CM CR = False+ type instance (:==) CM CS = False+ type instance (:==) CM CT = False+ type instance (:==) CM CU = False+ type instance (:==) CM CV = False+ type instance (:==) CM CW = False+ type instance (:==) CM CX = False+ type instance (:==) CM CY = False+ type instance (:==) CM CZ = False+ type instance (:==) CN CA = False+ type instance (:==) CN CB = False+ type instance (:==) CN CC = False+ type instance (:==) CN CD = False+ type instance (:==) CN CE = False+ type instance (:==) CN CF = False+ type instance (:==) CN CG = False+ type instance (:==) CN CH = False+ type instance (:==) CN CI = False+ type instance (:==) CN CJ = False+ type instance (:==) CN CK = False+ type instance (:==) CN CL = False+ type instance (:==) CN CM = False+ type instance (:==) CN CN = True+ type instance (:==) CN CO = False+ type instance (:==) CN CP = False+ type instance (:==) CN CQ = False+ type instance (:==) CN CR = False+ type instance (:==) CN CS = False+ type instance (:==) CN CT = False+ type instance (:==) CN CU = False+ type instance (:==) CN CV = False+ type instance (:==) CN CW = False+ type instance (:==) CN CX = False+ type instance (:==) CN CY = False+ type instance (:==) CN CZ = False+ type instance (:==) CO CA = False+ type instance (:==) CO CB = False+ type instance (:==) CO CC = False+ type instance (:==) CO CD = False+ type instance (:==) CO CE = False+ type instance (:==) CO CF = False+ type instance (:==) CO CG = False+ type instance (:==) CO CH = False+ type instance (:==) CO CI = False+ type instance (:==) CO CJ = False+ type instance (:==) CO CK = False+ type instance (:==) CO CL = False+ type instance (:==) CO CM = False+ type instance (:==) CO CN = False+ type instance (:==) CO CO = True+ type instance (:==) CO CP = False+ type instance (:==) CO CQ = False+ type instance (:==) CO CR = False+ type instance (:==) CO CS = False+ type instance (:==) CO CT = False+ type instance (:==) CO CU = False+ type instance (:==) CO CV = False+ type instance (:==) CO CW = False+ type instance (:==) CO CX = False+ type instance (:==) CO CY = False+ type instance (:==) CO CZ = False+ type instance (:==) CP CA = False+ type instance (:==) CP CB = False+ type instance (:==) CP CC = False+ type instance (:==) CP CD = False+ type instance (:==) CP CE = False+ type instance (:==) CP CF = False+ type instance (:==) CP CG = False+ type instance (:==) CP CH = False+ type instance (:==) CP CI = False+ type instance (:==) CP CJ = False+ type instance (:==) CP CK = False+ type instance (:==) CP CL = False+ type instance (:==) CP CM = False+ type instance (:==) CP CN = False+ type instance (:==) CP CO = False+ type instance (:==) CP CP = True+ type instance (:==) CP CQ = False+ type instance (:==) CP CR = False+ type instance (:==) CP CS = False+ type instance (:==) CP CT = False+ type instance (:==) CP CU = False+ type instance (:==) CP CV = False+ type instance (:==) CP CW = False+ type instance (:==) CP CX = False+ type instance (:==) CP CY = False+ type instance (:==) CP CZ = False+ type instance (:==) CQ CA = False+ type instance (:==) CQ CB = False+ type instance (:==) CQ CC = False+ type instance (:==) CQ CD = False+ type instance (:==) CQ CE = False+ type instance (:==) CQ CF = False+ type instance (:==) CQ CG = False+ type instance (:==) CQ CH = False+ type instance (:==) CQ CI = False+ type instance (:==) CQ CJ = False+ type instance (:==) CQ CK = False+ type instance (:==) CQ CL = False+ type instance (:==) CQ CM = False+ type instance (:==) CQ CN = False+ type instance (:==) CQ CO = False+ type instance (:==) CQ CP = False+ type instance (:==) CQ CQ = True+ type instance (:==) CQ CR = False+ type instance (:==) CQ CS = False+ type instance (:==) CQ CT = False+ type instance (:==) CQ CU = False+ type instance (:==) CQ CV = False+ type instance (:==) CQ CW = False+ type instance (:==) CQ CX = False+ type instance (:==) CQ CY = False+ type instance (:==) CQ CZ = False+ type instance (:==) CR CA = False+ type instance (:==) CR CB = False+ type instance (:==) CR CC = False+ type instance (:==) CR CD = False+ type instance (:==) CR CE = False+ type instance (:==) CR CF = False+ type instance (:==) CR CG = False+ type instance (:==) CR CH = False+ type instance (:==) CR CI = False+ type instance (:==) CR CJ = False+ type instance (:==) CR CK = False+ type instance (:==) CR CL = False+ type instance (:==) CR CM = False+ type instance (:==) CR CN = False+ type instance (:==) CR CO = False+ type instance (:==) CR CP = False+ type instance (:==) CR CQ = False+ type instance (:==) CR CR = True+ type instance (:==) CR CS = False+ type instance (:==) CR CT = False+ type instance (:==) CR CU = False+ type instance (:==) CR CV = False+ type instance (:==) CR CW = False+ type instance (:==) CR CX = False+ type instance (:==) CR CY = False+ type instance (:==) CR CZ = False+ type instance (:==) CS CA = False+ type instance (:==) CS CB = False+ type instance (:==) CS CC = False+ type instance (:==) CS CD = False+ type instance (:==) CS CE = False+ type instance (:==) CS CF = False+ type instance (:==) CS CG = False+ type instance (:==) CS CH = False+ type instance (:==) CS CI = False+ type instance (:==) CS CJ = False+ type instance (:==) CS CK = False+ type instance (:==) CS CL = False+ type instance (:==) CS CM = False+ type instance (:==) CS CN = False+ type instance (:==) CS CO = False+ type instance (:==) CS CP = False+ type instance (:==) CS CQ = False+ type instance (:==) CS CR = False+ type instance (:==) CS CS = True+ type instance (:==) CS CT = False+ type instance (:==) CS CU = False+ type instance (:==) CS CV = False+ type instance (:==) CS CW = False+ type instance (:==) CS CX = False+ type instance (:==) CS CY = False+ type instance (:==) CS CZ = False+ type instance (:==) CT CA = False+ type instance (:==) CT CB = False+ type instance (:==) CT CC = False+ type instance (:==) CT CD = False+ type instance (:==) CT CE = False+ type instance (:==) CT CF = False+ type instance (:==) CT CG = False+ type instance (:==) CT CH = False+ type instance (:==) CT CI = False+ type instance (:==) CT CJ = False+ type instance (:==) CT CK = False+ type instance (:==) CT CL = False+ type instance (:==) CT CM = False+ type instance (:==) CT CN = False+ type instance (:==) CT CO = False+ type instance (:==) CT CP = False+ type instance (:==) CT CQ = False+ type instance (:==) CT CR = False+ type instance (:==) CT CS = False+ type instance (:==) CT CT = True+ type instance (:==) CT CU = False+ type instance (:==) CT CV = False+ type instance (:==) CT CW = False+ type instance (:==) CT CX = False+ type instance (:==) CT CY = False+ type instance (:==) CT CZ = False+ type instance (:==) CU CA = False+ type instance (:==) CU CB = False+ type instance (:==) CU CC = False+ type instance (:==) CU CD = False+ type instance (:==) CU CE = False+ type instance (:==) CU CF = False+ type instance (:==) CU CG = False+ type instance (:==) CU CH = False+ type instance (:==) CU CI = False+ type instance (:==) CU CJ = False+ type instance (:==) CU CK = False+ type instance (:==) CU CL = False+ type instance (:==) CU CM = False+ type instance (:==) CU CN = False+ type instance (:==) CU CO = False+ type instance (:==) CU CP = False+ type instance (:==) CU CQ = False+ type instance (:==) CU CR = False+ type instance (:==) CU CS = False+ type instance (:==) CU CT = False+ type instance (:==) CU CU = True+ type instance (:==) CU CV = False+ type instance (:==) CU CW = False+ type instance (:==) CU CX = False+ type instance (:==) CU CY = False+ type instance (:==) CU CZ = False+ type instance (:==) CV CA = False+ type instance (:==) CV CB = False+ type instance (:==) CV CC = False+ type instance (:==) CV CD = False+ type instance (:==) CV CE = False+ type instance (:==) CV CF = False+ type instance (:==) CV CG = False+ type instance (:==) CV CH = False+ type instance (:==) CV CI = False+ type instance (:==) CV CJ = False+ type instance (:==) CV CK = False+ type instance (:==) CV CL = False+ type instance (:==) CV CM = False+ type instance (:==) CV CN = False+ type instance (:==) CV CO = False+ type instance (:==) CV CP = False+ type instance (:==) CV CQ = False+ type instance (:==) CV CR = False+ type instance (:==) CV CS = False+ type instance (:==) CV CT = False+ type instance (:==) CV CU = False+ type instance (:==) CV CV = True+ type instance (:==) CV CW = False+ type instance (:==) CV CX = False+ type instance (:==) CV CY = False+ type instance (:==) CV CZ = False+ type instance (:==) CW CA = False+ type instance (:==) CW CB = False+ type instance (:==) CW CC = False+ type instance (:==) CW CD = False+ type instance (:==) CW CE = False+ type instance (:==) CW CF = False+ type instance (:==) CW CG = False+ type instance (:==) CW CH = False+ type instance (:==) CW CI = False+ type instance (:==) CW CJ = False+ type instance (:==) CW CK = False+ type instance (:==) CW CL = False+ type instance (:==) CW CM = False+ type instance (:==) CW CN = False+ type instance (:==) CW CO = False+ type instance (:==) CW CP = False+ type instance (:==) CW CQ = False+ type instance (:==) CW CR = False+ type instance (:==) CW CS = False+ type instance (:==) CW CT = False+ type instance (:==) CW CU = False+ type instance (:==) CW CV = False+ type instance (:==) CW CW = True+ type instance (:==) CW CX = False+ type instance (:==) CW CY = False+ type instance (:==) CW CZ = False+ type instance (:==) CX CA = False+ type instance (:==) CX CB = False+ type instance (:==) CX CC = False+ type instance (:==) CX CD = False+ type instance (:==) CX CE = False+ type instance (:==) CX CF = False+ type instance (:==) CX CG = False+ type instance (:==) CX CH = False+ type instance (:==) CX CI = False+ type instance (:==) CX CJ = False+ type instance (:==) CX CK = False+ type instance (:==) CX CL = False+ type instance (:==) CX CM = False+ type instance (:==) CX CN = False+ type instance (:==) CX CO = False+ type instance (:==) CX CP = False+ type instance (:==) CX CQ = False+ type instance (:==) CX CR = False+ type instance (:==) CX CS = False+ type instance (:==) CX CT = False+ type instance (:==) CX CU = False+ type instance (:==) CX CV = False+ type instance (:==) CX CW = False+ type instance (:==) CX CX = True+ type instance (:==) CX CY = False+ type instance (:==) CX CZ = False+ type instance (:==) CY CA = False+ type instance (:==) CY CB = False+ type instance (:==) CY CC = False+ type instance (:==) CY CD = False+ type instance (:==) CY CE = False+ type instance (:==) CY CF = False+ type instance (:==) CY CG = False+ type instance (:==) CY CH = False+ type instance (:==) CY CI = False+ type instance (:==) CY CJ = False+ type instance (:==) CY CK = False+ type instance (:==) CY CL = False+ type instance (:==) CY CM = False+ type instance (:==) CY CN = False+ type instance (:==) CY CO = False+ type instance (:==) CY CP = False+ type instance (:==) CY CQ = False+ type instance (:==) CY CR = False+ type instance (:==) CY CS = False+ type instance (:==) CY CT = False+ type instance (:==) CY CU = False+ type instance (:==) CY CV = False+ type instance (:==) CY CW = False+ type instance (:==) CY CX = False+ type instance (:==) CY CY = True+ type instance (:==) CY CZ = False+ type instance (:==) CZ CA = False+ type instance (:==) CZ CB = False+ type instance (:==) CZ CC = False+ type instance (:==) CZ CD = False+ type instance (:==) CZ CE = False+ type instance (:==) CZ CF = False+ type instance (:==) CZ CG = False+ type instance (:==) CZ CH = False+ type instance (:==) CZ CI = False+ type instance (:==) CZ CJ = False+ type instance (:==) CZ CK = False+ type instance (:==) CZ CL = False+ type instance (:==) CZ CM = False+ type instance (:==) CZ CN = False+ type instance (:==) CZ CO = False+ type instance (:==) CZ CP = False+ type instance (:==) CZ CQ = False+ type instance (:==) CZ CR = False+ type instance (:==) CZ CS = False+ type instance (:==) CZ CT = False+ type instance (:==) CZ CU = False+ type instance (:==) CZ CV = False+ type instance (:==) CZ CW = False+ type instance (:==) CZ CX = False+ type instance (:==) CZ CY = False+ type instance (:==) CZ CZ = True+ type instance Append (Sch s1) (Sch s2) = Sch (:++ s1 s2)+ type instance AttrNotIn z (Sch GHC.Types.[]) = True+ type instance AttrNotIn (Attr name u) (Sch (GHC.Types.: (Attr name' z) t)) =+ :&& (:/= name name') (AttrNotIn (Attr name u) (Sch t))+ type instance Disjoint (Sch GHC.Types.[]) z = True+ type instance Disjoint (Sch (GHC.Types.: h t)) s =+ :&& (AttrNotIn h s) (Disjoint (Sch t) s)+ type instance Occurs z (Sch GHC.Types.[]) = False+ type instance Occurs name (Sch (GHC.Types.: (Attr name' z) attrs)) =+ :|| (:== name name') (Occurs name (Sch attrs))+ type instance Lookup z (Sch GHC.Types.[]) = Any+ type instance Lookup name (Sch (GHC.Types.: (Attr name' u) attrs)) =+ If (:== name name') u (Lookup name (Sch attrs))+ type family Append (a :: Schema) (a :: Schema) :: Schema+ type family AttrNotIn (a :: Attribute) (a :: Schema) :: Bool+ type family Disjoint (a :: Schema) (a :: Schema) :: Bool+ type family Occurs (a :: [AChar]) (a :: Schema) :: Bool+ type family Lookup (a :: [AChar]) (a :: Schema) :: U+ data instance Sing (z :: U)+ = z ~ BOOL => SBOOL |+ z ~ STRING => SSTRING |+ z ~ NAT => SNAT |+ forall (n :: U) (n :: Nat). z ~ VEC n n => SVEC (Sing n) (Sing n)+ type SU (z :: U) = Sing z+ instance SingKind (KProxy :: KProxy U) where+ type instance DemoteRep (KProxy :: KProxy U) = U+ fromSing SBOOL = BOOL+ fromSing SSTRING = STRING+ fromSing SNAT = NAT+ fromSing (SVEC b b) = VEC (fromSing b) (fromSing b)+ toSing BOOL = SomeSing SBOOL+ toSing STRING = SomeSing SSTRING+ toSing NAT = SomeSing SNAT+ toSing (VEC b b)+ = case+ (toSing b :: SomeSing (KProxy :: KProxy U), + toSing b :: SomeSing (KProxy :: KProxy Nat))+ of {+ (SomeSing c, SomeSing c) -> SomeSing (SVEC c c) }+ instance SEq (KProxy :: KProxy U) where+ %:== SBOOL SBOOL = STrue+ %:== SBOOL SSTRING = SFalse+ %:== SBOOL SNAT = SFalse+ %:== SBOOL (SVEC _ _) = SFalse+ %:== SSTRING SBOOL = SFalse+ %:== SSTRING SSTRING = STrue+ %:== SSTRING SNAT = SFalse+ %:== SSTRING (SVEC _ _) = SFalse+ %:== SNAT SBOOL = SFalse+ %:== SNAT SSTRING = SFalse+ %:== SNAT SNAT = STrue+ %:== SNAT (SVEC _ _) = SFalse+ %:== (SVEC _ _) SBOOL = SFalse+ %:== (SVEC _ _) SSTRING = SFalse+ %:== (SVEC _ _) SNAT = SFalse+ %:== (SVEC a a) (SVEC b b) = (%:&&) ((%:==) a b) ((%:==) a b)+ instance SDecide (KProxy :: KProxy U) where+ %~ SBOOL SBOOL = Proved Refl+ %~ SBOOL SSTRING+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SBOOL SNAT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SBOOL (SVEC _ _)+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SSTRING SBOOL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SSTRING SSTRING = Proved Refl+ %~ SSTRING SNAT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SSTRING (SVEC _ _)+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SNAT SBOOL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SNAT SSTRING+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SNAT SNAT = Proved Refl+ %~ SNAT (SVEC _ _)+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ (SVEC _ _) SBOOL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ (SVEC _ _) SSTRING+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ (SVEC _ _) SNAT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ (SVEC a a) (SVEC b b)+ = case ((%~) a b, (%~) a b) of {+ (Proved Refl, Proved Refl) -> Proved Refl+ (Disproved contra, _) -> Disproved (\ Refl -> contra Refl)+ (_, Disproved contra) -> Disproved (\ Refl -> contra Refl) }+ instance SingI BOOL where+ sing = SBOOL+ instance SingI STRING where+ sing = SSTRING+ instance SingI NAT where+ sing = SNAT+ instance (SingI n, SingI n) =>+ SingI (VEC (n :: U) (n :: Nat)) where+ sing = SVEC sing sing+ data instance Sing (z :: AChar)+ = z ~ CA => SCA |+ z ~ CB => SCB |+ z ~ CC => SCC |+ z ~ CD => SCD |+ z ~ CE => SCE |+ z ~ CF => SCF |+ z ~ CG => SCG |+ z ~ CH => SCH |+ z ~ CI => SCI |+ z ~ CJ => SCJ |+ z ~ CK => SCK |+ z ~ CL => SCL |+ z ~ CM => SCM |+ z ~ CN => SCN |+ z ~ CO => SCO |+ z ~ CP => SCP |+ z ~ CQ => SCQ |+ z ~ CR => SCR |+ z ~ CS => SCS |+ z ~ CT => SCT |+ z ~ CU => SCU |+ z ~ CV => SCV |+ z ~ CW => SCW |+ z ~ CX => SCX |+ z ~ CY => SCY |+ z ~ CZ => SCZ+ type SAChar (z :: AChar) = Sing z+ instance SingKind (KProxy :: KProxy AChar) where+ type instance DemoteRep (KProxy :: KProxy AChar) = AChar+ fromSing SCA = CA+ fromSing SCB = CB+ fromSing SCC = CC+ fromSing SCD = CD+ fromSing SCE = CE+ fromSing SCF = CF+ fromSing SCG = CG+ fromSing SCH = CH+ fromSing SCI = CI+ fromSing SCJ = CJ+ fromSing SCK = CK+ fromSing SCL = CL+ fromSing SCM = CM+ fromSing SCN = CN+ fromSing SCO = CO+ fromSing SCP = CP+ fromSing SCQ = CQ+ fromSing SCR = CR+ fromSing SCS = CS+ fromSing SCT = CT+ fromSing SCU = CU+ fromSing SCV = CV+ fromSing SCW = CW+ fromSing SCX = CX+ fromSing SCY = CY+ fromSing SCZ = CZ+ toSing CA = SomeSing SCA+ toSing CB = SomeSing SCB+ toSing CC = SomeSing SCC+ toSing CD = SomeSing SCD+ toSing CE = SomeSing SCE+ toSing CF = SomeSing SCF+ toSing CG = SomeSing SCG+ toSing CH = SomeSing SCH+ toSing CI = SomeSing SCI+ toSing CJ = SomeSing SCJ+ toSing CK = SomeSing SCK+ toSing CL = SomeSing SCL+ toSing CM = SomeSing SCM+ toSing CN = SomeSing SCN+ toSing CO = SomeSing SCO+ toSing CP = SomeSing SCP+ toSing CQ = SomeSing SCQ+ toSing CR = SomeSing SCR+ toSing CS = SomeSing SCS+ toSing CT = SomeSing SCT+ toSing CU = SomeSing SCU+ toSing CV = SomeSing SCV+ toSing CW = SomeSing SCW+ toSing CX = SomeSing SCX+ toSing CY = SomeSing SCY+ toSing CZ = SomeSing SCZ+ instance SEq (KProxy :: KProxy AChar) where+ %:== SCA SCA = STrue+ %:== SCA SCB = SFalse+ %:== SCA SCC = SFalse+ %:== SCA SCD = SFalse+ %:== SCA SCE = SFalse+ %:== SCA SCF = SFalse+ %:== SCA SCG = SFalse+ %:== SCA SCH = SFalse+ %:== SCA SCI = SFalse+ %:== SCA SCJ = SFalse+ %:== SCA SCK = SFalse+ %:== SCA SCL = SFalse+ %:== SCA SCM = SFalse+ %:== SCA SCN = SFalse+ %:== SCA SCO = SFalse+ %:== SCA SCP = SFalse+ %:== SCA SCQ = SFalse+ %:== SCA SCR = SFalse+ %:== SCA SCS = SFalse+ %:== SCA SCT = SFalse+ %:== SCA SCU = SFalse+ %:== SCA SCV = SFalse+ %:== SCA SCW = SFalse+ %:== SCA SCX = SFalse+ %:== SCA SCY = SFalse+ %:== SCA SCZ = SFalse+ %:== SCB SCA = SFalse+ %:== SCB SCB = STrue+ %:== SCB SCC = SFalse+ %:== SCB SCD = SFalse+ %:== SCB SCE = SFalse+ %:== SCB SCF = SFalse+ %:== SCB SCG = SFalse+ %:== SCB SCH = SFalse+ %:== SCB SCI = SFalse+ %:== SCB SCJ = SFalse+ %:== SCB SCK = SFalse+ %:== SCB SCL = SFalse+ %:== SCB SCM = SFalse+ %:== SCB SCN = SFalse+ %:== SCB SCO = SFalse+ %:== SCB SCP = SFalse+ %:== SCB SCQ = SFalse+ %:== SCB SCR = SFalse+ %:== SCB SCS = SFalse+ %:== SCB SCT = SFalse+ %:== SCB SCU = SFalse+ %:== SCB SCV = SFalse+ %:== SCB SCW = SFalse+ %:== SCB SCX = SFalse+ %:== SCB SCY = SFalse+ %:== SCB SCZ = SFalse+ %:== SCC SCA = SFalse+ %:== SCC SCB = SFalse+ %:== SCC SCC = STrue+ %:== SCC SCD = SFalse+ %:== SCC SCE = SFalse+ %:== SCC SCF = SFalse+ %:== SCC SCG = SFalse+ %:== SCC SCH = SFalse+ %:== SCC SCI = SFalse+ %:== SCC SCJ = SFalse+ %:== SCC SCK = SFalse+ %:== SCC SCL = SFalse+ %:== SCC SCM = SFalse+ %:== SCC SCN = SFalse+ %:== SCC SCO = SFalse+ %:== SCC SCP = SFalse+ %:== SCC SCQ = SFalse+ %:== SCC SCR = SFalse+ %:== SCC SCS = SFalse+ %:== SCC SCT = SFalse+ %:== SCC SCU = SFalse+ %:== SCC SCV = SFalse+ %:== SCC SCW = SFalse+ %:== SCC SCX = SFalse+ %:== SCC SCY = SFalse+ %:== SCC SCZ = SFalse+ %:== SCD SCA = SFalse+ %:== SCD SCB = SFalse+ %:== SCD SCC = SFalse+ %:== SCD SCD = STrue+ %:== SCD SCE = SFalse+ %:== SCD SCF = SFalse+ %:== SCD SCG = SFalse+ %:== SCD SCH = SFalse+ %:== SCD SCI = SFalse+ %:== SCD SCJ = SFalse+ %:== SCD SCK = SFalse+ %:== SCD SCL = SFalse+ %:== SCD SCM = SFalse+ %:== SCD SCN = SFalse+ %:== SCD SCO = SFalse+ %:== SCD SCP = SFalse+ %:== SCD SCQ = SFalse+ %:== SCD SCR = SFalse+ %:== SCD SCS = SFalse+ %:== SCD SCT = SFalse+ %:== SCD SCU = SFalse+ %:== SCD SCV = SFalse+ %:== SCD SCW = SFalse+ %:== SCD SCX = SFalse+ %:== SCD SCY = SFalse+ %:== SCD SCZ = SFalse+ %:== SCE SCA = SFalse+ %:== SCE SCB = SFalse+ %:== SCE SCC = SFalse+ %:== SCE SCD = SFalse+ %:== SCE SCE = STrue+ %:== SCE SCF = SFalse+ %:== SCE SCG = SFalse+ %:== SCE SCH = SFalse+ %:== SCE SCI = SFalse+ %:== SCE SCJ = SFalse+ %:== SCE SCK = SFalse+ %:== SCE SCL = SFalse+ %:== SCE SCM = SFalse+ %:== SCE SCN = SFalse+ %:== SCE SCO = SFalse+ %:== SCE SCP = SFalse+ %:== SCE SCQ = SFalse+ %:== SCE SCR = SFalse+ %:== SCE SCS = SFalse+ %:== SCE SCT = SFalse+ %:== SCE SCU = SFalse+ %:== SCE SCV = SFalse+ %:== SCE SCW = SFalse+ %:== SCE SCX = SFalse+ %:== SCE SCY = SFalse+ %:== SCE SCZ = SFalse+ %:== SCF SCA = SFalse+ %:== SCF SCB = SFalse+ %:== SCF SCC = SFalse+ %:== SCF SCD = SFalse+ %:== SCF SCE = SFalse+ %:== SCF SCF = STrue+ %:== SCF SCG = SFalse+ %:== SCF SCH = SFalse+ %:== SCF SCI = SFalse+ %:== SCF SCJ = SFalse+ %:== SCF SCK = SFalse+ %:== SCF SCL = SFalse+ %:== SCF SCM = SFalse+ %:== SCF SCN = SFalse+ %:== SCF SCO = SFalse+ %:== SCF SCP = SFalse+ %:== SCF SCQ = SFalse+ %:== SCF SCR = SFalse+ %:== SCF SCS = SFalse+ %:== SCF SCT = SFalse+ %:== SCF SCU = SFalse+ %:== SCF SCV = SFalse+ %:== SCF SCW = SFalse+ %:== SCF SCX = SFalse+ %:== SCF SCY = SFalse+ %:== SCF SCZ = SFalse+ %:== SCG SCA = SFalse+ %:== SCG SCB = SFalse+ %:== SCG SCC = SFalse+ %:== SCG SCD = SFalse+ %:== SCG SCE = SFalse+ %:== SCG SCF = SFalse+ %:== SCG SCG = STrue+ %:== SCG SCH = SFalse+ %:== SCG SCI = SFalse+ %:== SCG SCJ = SFalse+ %:== SCG SCK = SFalse+ %:== SCG SCL = SFalse+ %:== SCG SCM = SFalse+ %:== SCG SCN = SFalse+ %:== SCG SCO = SFalse+ %:== SCG SCP = SFalse+ %:== SCG SCQ = SFalse+ %:== SCG SCR = SFalse+ %:== SCG SCS = SFalse+ %:== SCG SCT = SFalse+ %:== SCG SCU = SFalse+ %:== SCG SCV = SFalse+ %:== SCG SCW = SFalse+ %:== SCG SCX = SFalse+ %:== SCG SCY = SFalse+ %:== SCG SCZ = SFalse+ %:== SCH SCA = SFalse+ %:== SCH SCB = SFalse+ %:== SCH SCC = SFalse+ %:== SCH SCD = SFalse+ %:== SCH SCE = SFalse+ %:== SCH SCF = SFalse+ %:== SCH SCG = SFalse+ %:== SCH SCH = STrue+ %:== SCH SCI = SFalse+ %:== SCH SCJ = SFalse+ %:== SCH SCK = SFalse+ %:== SCH SCL = SFalse+ %:== SCH SCM = SFalse+ %:== SCH SCN = SFalse+ %:== SCH SCO = SFalse+ %:== SCH SCP = SFalse+ %:== SCH SCQ = SFalse+ %:== SCH SCR = SFalse+ %:== SCH SCS = SFalse+ %:== SCH SCT = SFalse+ %:== SCH SCU = SFalse+ %:== SCH SCV = SFalse+ %:== SCH SCW = SFalse+ %:== SCH SCX = SFalse+ %:== SCH SCY = SFalse+ %:== SCH SCZ = SFalse+ %:== SCI SCA = SFalse+ %:== SCI SCB = SFalse+ %:== SCI SCC = SFalse+ %:== SCI SCD = SFalse+ %:== SCI SCE = SFalse+ %:== SCI SCF = SFalse+ %:== SCI SCG = SFalse+ %:== SCI SCH = SFalse+ %:== SCI SCI = STrue+ %:== SCI SCJ = SFalse+ %:== SCI SCK = SFalse+ %:== SCI SCL = SFalse+ %:== SCI SCM = SFalse+ %:== SCI SCN = SFalse+ %:== SCI SCO = SFalse+ %:== SCI SCP = SFalse+ %:== SCI SCQ = SFalse+ %:== SCI SCR = SFalse+ %:== SCI SCS = SFalse+ %:== SCI SCT = SFalse+ %:== SCI SCU = SFalse+ %:== SCI SCV = SFalse+ %:== SCI SCW = SFalse+ %:== SCI SCX = SFalse+ %:== SCI SCY = SFalse+ %:== SCI SCZ = SFalse+ %:== SCJ SCA = SFalse+ %:== SCJ SCB = SFalse+ %:== SCJ SCC = SFalse+ %:== SCJ SCD = SFalse+ %:== SCJ SCE = SFalse+ %:== SCJ SCF = SFalse+ %:== SCJ SCG = SFalse+ %:== SCJ SCH = SFalse+ %:== SCJ SCI = SFalse+ %:== SCJ SCJ = STrue+ %:== SCJ SCK = SFalse+ %:== SCJ SCL = SFalse+ %:== SCJ SCM = SFalse+ %:== SCJ SCN = SFalse+ %:== SCJ SCO = SFalse+ %:== SCJ SCP = SFalse+ %:== SCJ SCQ = SFalse+ %:== SCJ SCR = SFalse+ %:== SCJ SCS = SFalse+ %:== SCJ SCT = SFalse+ %:== SCJ SCU = SFalse+ %:== SCJ SCV = SFalse+ %:== SCJ SCW = SFalse+ %:== SCJ SCX = SFalse+ %:== SCJ SCY = SFalse+ %:== SCJ SCZ = SFalse+ %:== SCK SCA = SFalse+ %:== SCK SCB = SFalse+ %:== SCK SCC = SFalse+ %:== SCK SCD = SFalse+ %:== SCK SCE = SFalse+ %:== SCK SCF = SFalse+ %:== SCK SCG = SFalse+ %:== SCK SCH = SFalse+ %:== SCK SCI = SFalse+ %:== SCK SCJ = SFalse+ %:== SCK SCK = STrue+ %:== SCK SCL = SFalse+ %:== SCK SCM = SFalse+ %:== SCK SCN = SFalse+ %:== SCK SCO = SFalse+ %:== SCK SCP = SFalse+ %:== SCK SCQ = SFalse+ %:== SCK SCR = SFalse+ %:== SCK SCS = SFalse+ %:== SCK SCT = SFalse+ %:== SCK SCU = SFalse+ %:== SCK SCV = SFalse+ %:== SCK SCW = SFalse+ %:== SCK SCX = SFalse+ %:== SCK SCY = SFalse+ %:== SCK SCZ = SFalse+ %:== SCL SCA = SFalse+ %:== SCL SCB = SFalse+ %:== SCL SCC = SFalse+ %:== SCL SCD = SFalse+ %:== SCL SCE = SFalse+ %:== SCL SCF = SFalse+ %:== SCL SCG = SFalse+ %:== SCL SCH = SFalse+ %:== SCL SCI = SFalse+ %:== SCL SCJ = SFalse+ %:== SCL SCK = SFalse+ %:== SCL SCL = STrue+ %:== SCL SCM = SFalse+ %:== SCL SCN = SFalse+ %:== SCL SCO = SFalse+ %:== SCL SCP = SFalse+ %:== SCL SCQ = SFalse+ %:== SCL SCR = SFalse+ %:== SCL SCS = SFalse+ %:== SCL SCT = SFalse+ %:== SCL SCU = SFalse+ %:== SCL SCV = SFalse+ %:== SCL SCW = SFalse+ %:== SCL SCX = SFalse+ %:== SCL SCY = SFalse+ %:== SCL SCZ = SFalse+ %:== SCM SCA = SFalse+ %:== SCM SCB = SFalse+ %:== SCM SCC = SFalse+ %:== SCM SCD = SFalse+ %:== SCM SCE = SFalse+ %:== SCM SCF = SFalse+ %:== SCM SCG = SFalse+ %:== SCM SCH = SFalse+ %:== SCM SCI = SFalse+ %:== SCM SCJ = SFalse+ %:== SCM SCK = SFalse+ %:== SCM SCL = SFalse+ %:== SCM SCM = STrue+ %:== SCM SCN = SFalse+ %:== SCM SCO = SFalse+ %:== SCM SCP = SFalse+ %:== SCM SCQ = SFalse+ %:== SCM SCR = SFalse+ %:== SCM SCS = SFalse+ %:== SCM SCT = SFalse+ %:== SCM SCU = SFalse+ %:== SCM SCV = SFalse+ %:== SCM SCW = SFalse+ %:== SCM SCX = SFalse+ %:== SCM SCY = SFalse+ %:== SCM SCZ = SFalse+ %:== SCN SCA = SFalse+ %:== SCN SCB = SFalse+ %:== SCN SCC = SFalse+ %:== SCN SCD = SFalse+ %:== SCN SCE = SFalse+ %:== SCN SCF = SFalse+ %:== SCN SCG = SFalse+ %:== SCN SCH = SFalse+ %:== SCN SCI = SFalse+ %:== SCN SCJ = SFalse+ %:== SCN SCK = SFalse+ %:== SCN SCL = SFalse+ %:== SCN SCM = SFalse+ %:== SCN SCN = STrue+ %:== SCN SCO = SFalse+ %:== SCN SCP = SFalse+ %:== SCN SCQ = SFalse+ %:== SCN SCR = SFalse+ %:== SCN SCS = SFalse+ %:== SCN SCT = SFalse+ %:== SCN SCU = SFalse+ %:== SCN SCV = SFalse+ %:== SCN SCW = SFalse+ %:== SCN SCX = SFalse+ %:== SCN SCY = SFalse+ %:== SCN SCZ = SFalse+ %:== SCO SCA = SFalse+ %:== SCO SCB = SFalse+ %:== SCO SCC = SFalse+ %:== SCO SCD = SFalse+ %:== SCO SCE = SFalse+ %:== SCO SCF = SFalse+ %:== SCO SCG = SFalse+ %:== SCO SCH = SFalse+ %:== SCO SCI = SFalse+ %:== SCO SCJ = SFalse+ %:== SCO SCK = SFalse+ %:== SCO SCL = SFalse+ %:== SCO SCM = SFalse+ %:== SCO SCN = SFalse+ %:== SCO SCO = STrue+ %:== SCO SCP = SFalse+ %:== SCO SCQ = SFalse+ %:== SCO SCR = SFalse+ %:== SCO SCS = SFalse+ %:== SCO SCT = SFalse+ %:== SCO SCU = SFalse+ %:== SCO SCV = SFalse+ %:== SCO SCW = SFalse+ %:== SCO SCX = SFalse+ %:== SCO SCY = SFalse+ %:== SCO SCZ = SFalse+ %:== SCP SCA = SFalse+ %:== SCP SCB = SFalse+ %:== SCP SCC = SFalse+ %:== SCP SCD = SFalse+ %:== SCP SCE = SFalse+ %:== SCP SCF = SFalse+ %:== SCP SCG = SFalse+ %:== SCP SCH = SFalse+ %:== SCP SCI = SFalse+ %:== SCP SCJ = SFalse+ %:== SCP SCK = SFalse+ %:== SCP SCL = SFalse+ %:== SCP SCM = SFalse+ %:== SCP SCN = SFalse+ %:== SCP SCO = SFalse+ %:== SCP SCP = STrue+ %:== SCP SCQ = SFalse+ %:== SCP SCR = SFalse+ %:== SCP SCS = SFalse+ %:== SCP SCT = SFalse+ %:== SCP SCU = SFalse+ %:== SCP SCV = SFalse+ %:== SCP SCW = SFalse+ %:== SCP SCX = SFalse+ %:== SCP SCY = SFalse+ %:== SCP SCZ = SFalse+ %:== SCQ SCA = SFalse+ %:== SCQ SCB = SFalse+ %:== SCQ SCC = SFalse+ %:== SCQ SCD = SFalse+ %:== SCQ SCE = SFalse+ %:== SCQ SCF = SFalse+ %:== SCQ SCG = SFalse+ %:== SCQ SCH = SFalse+ %:== SCQ SCI = SFalse+ %:== SCQ SCJ = SFalse+ %:== SCQ SCK = SFalse+ %:== SCQ SCL = SFalse+ %:== SCQ SCM = SFalse+ %:== SCQ SCN = SFalse+ %:== SCQ SCO = SFalse+ %:== SCQ SCP = SFalse+ %:== SCQ SCQ = STrue+ %:== SCQ SCR = SFalse+ %:== SCQ SCS = SFalse+ %:== SCQ SCT = SFalse+ %:== SCQ SCU = SFalse+ %:== SCQ SCV = SFalse+ %:== SCQ SCW = SFalse+ %:== SCQ SCX = SFalse+ %:== SCQ SCY = SFalse+ %:== SCQ SCZ = SFalse+ %:== SCR SCA = SFalse+ %:== SCR SCB = SFalse+ %:== SCR SCC = SFalse+ %:== SCR SCD = SFalse+ %:== SCR SCE = SFalse+ %:== SCR SCF = SFalse+ %:== SCR SCG = SFalse+ %:== SCR SCH = SFalse+ %:== SCR SCI = SFalse+ %:== SCR SCJ = SFalse+ %:== SCR SCK = SFalse+ %:== SCR SCL = SFalse+ %:== SCR SCM = SFalse+ %:== SCR SCN = SFalse+ %:== SCR SCO = SFalse+ %:== SCR SCP = SFalse+ %:== SCR SCQ = SFalse+ %:== SCR SCR = STrue+ %:== SCR SCS = SFalse+ %:== SCR SCT = SFalse+ %:== SCR SCU = SFalse+ %:== SCR SCV = SFalse+ %:== SCR SCW = SFalse+ %:== SCR SCX = SFalse+ %:== SCR SCY = SFalse+ %:== SCR SCZ = SFalse+ %:== SCS SCA = SFalse+ %:== SCS SCB = SFalse+ %:== SCS SCC = SFalse+ %:== SCS SCD = SFalse+ %:== SCS SCE = SFalse+ %:== SCS SCF = SFalse+ %:== SCS SCG = SFalse+ %:== SCS SCH = SFalse+ %:== SCS SCI = SFalse+ %:== SCS SCJ = SFalse+ %:== SCS SCK = SFalse+ %:== SCS SCL = SFalse+ %:== SCS SCM = SFalse+ %:== SCS SCN = SFalse+ %:== SCS SCO = SFalse+ %:== SCS SCP = SFalse+ %:== SCS SCQ = SFalse+ %:== SCS SCR = SFalse+ %:== SCS SCS = STrue+ %:== SCS SCT = SFalse+ %:== SCS SCU = SFalse+ %:== SCS SCV = SFalse+ %:== SCS SCW = SFalse+ %:== SCS SCX = SFalse+ %:== SCS SCY = SFalse+ %:== SCS SCZ = SFalse+ %:== SCT SCA = SFalse+ %:== SCT SCB = SFalse+ %:== SCT SCC = SFalse+ %:== SCT SCD = SFalse+ %:== SCT SCE = SFalse+ %:== SCT SCF = SFalse+ %:== SCT SCG = SFalse+ %:== SCT SCH = SFalse+ %:== SCT SCI = SFalse+ %:== SCT SCJ = SFalse+ %:== SCT SCK = SFalse+ %:== SCT SCL = SFalse+ %:== SCT SCM = SFalse+ %:== SCT SCN = SFalse+ %:== SCT SCO = SFalse+ %:== SCT SCP = SFalse+ %:== SCT SCQ = SFalse+ %:== SCT SCR = SFalse+ %:== SCT SCS = SFalse+ %:== SCT SCT = STrue+ %:== SCT SCU = SFalse+ %:== SCT SCV = SFalse+ %:== SCT SCW = SFalse+ %:== SCT SCX = SFalse+ %:== SCT SCY = SFalse+ %:== SCT SCZ = SFalse+ %:== SCU SCA = SFalse+ %:== SCU SCB = SFalse+ %:== SCU SCC = SFalse+ %:== SCU SCD = SFalse+ %:== SCU SCE = SFalse+ %:== SCU SCF = SFalse+ %:== SCU SCG = SFalse+ %:== SCU SCH = SFalse+ %:== SCU SCI = SFalse+ %:== SCU SCJ = SFalse+ %:== SCU SCK = SFalse+ %:== SCU SCL = SFalse+ %:== SCU SCM = SFalse+ %:== SCU SCN = SFalse+ %:== SCU SCO = SFalse+ %:== SCU SCP = SFalse+ %:== SCU SCQ = SFalse+ %:== SCU SCR = SFalse+ %:== SCU SCS = SFalse+ %:== SCU SCT = SFalse+ %:== SCU SCU = STrue+ %:== SCU SCV = SFalse+ %:== SCU SCW = SFalse+ %:== SCU SCX = SFalse+ %:== SCU SCY = SFalse+ %:== SCU SCZ = SFalse+ %:== SCV SCA = SFalse+ %:== SCV SCB = SFalse+ %:== SCV SCC = SFalse+ %:== SCV SCD = SFalse+ %:== SCV SCE = SFalse+ %:== SCV SCF = SFalse+ %:== SCV SCG = SFalse+ %:== SCV SCH = SFalse+ %:== SCV SCI = SFalse+ %:== SCV SCJ = SFalse+ %:== SCV SCK = SFalse+ %:== SCV SCL = SFalse+ %:== SCV SCM = SFalse+ %:== SCV SCN = SFalse+ %:== SCV SCO = SFalse+ %:== SCV SCP = SFalse+ %:== SCV SCQ = SFalse+ %:== SCV SCR = SFalse+ %:== SCV SCS = SFalse+ %:== SCV SCT = SFalse+ %:== SCV SCU = SFalse+ %:== SCV SCV = STrue+ %:== SCV SCW = SFalse+ %:== SCV SCX = SFalse+ %:== SCV SCY = SFalse+ %:== SCV SCZ = SFalse+ %:== SCW SCA = SFalse+ %:== SCW SCB = SFalse+ %:== SCW SCC = SFalse+ %:== SCW SCD = SFalse+ %:== SCW SCE = SFalse+ %:== SCW SCF = SFalse+ %:== SCW SCG = SFalse+ %:== SCW SCH = SFalse+ %:== SCW SCI = SFalse+ %:== SCW SCJ = SFalse+ %:== SCW SCK = SFalse+ %:== SCW SCL = SFalse+ %:== SCW SCM = SFalse+ %:== SCW SCN = SFalse+ %:== SCW SCO = SFalse+ %:== SCW SCP = SFalse+ %:== SCW SCQ = SFalse+ %:== SCW SCR = SFalse+ %:== SCW SCS = SFalse+ %:== SCW SCT = SFalse+ %:== SCW SCU = SFalse+ %:== SCW SCV = SFalse+ %:== SCW SCW = STrue+ %:== SCW SCX = SFalse+ %:== SCW SCY = SFalse+ %:== SCW SCZ = SFalse+ %:== SCX SCA = SFalse+ %:== SCX SCB = SFalse+ %:== SCX SCC = SFalse+ %:== SCX SCD = SFalse+ %:== SCX SCE = SFalse+ %:== SCX SCF = SFalse+ %:== SCX SCG = SFalse+ %:== SCX SCH = SFalse+ %:== SCX SCI = SFalse+ %:== SCX SCJ = SFalse+ %:== SCX SCK = SFalse+ %:== SCX SCL = SFalse+ %:== SCX SCM = SFalse+ %:== SCX SCN = SFalse+ %:== SCX SCO = SFalse+ %:== SCX SCP = SFalse+ %:== SCX SCQ = SFalse+ %:== SCX SCR = SFalse+ %:== SCX SCS = SFalse+ %:== SCX SCT = SFalse+ %:== SCX SCU = SFalse+ %:== SCX SCV = SFalse+ %:== SCX SCW = SFalse+ %:== SCX SCX = STrue+ %:== SCX SCY = SFalse+ %:== SCX SCZ = SFalse+ %:== SCY SCA = SFalse+ %:== SCY SCB = SFalse+ %:== SCY SCC = SFalse+ %:== SCY SCD = SFalse+ %:== SCY SCE = SFalse+ %:== SCY SCF = SFalse+ %:== SCY SCG = SFalse+ %:== SCY SCH = SFalse+ %:== SCY SCI = SFalse+ %:== SCY SCJ = SFalse+ %:== SCY SCK = SFalse+ %:== SCY SCL = SFalse+ %:== SCY SCM = SFalse+ %:== SCY SCN = SFalse+ %:== SCY SCO = SFalse+ %:== SCY SCP = SFalse+ %:== SCY SCQ = SFalse+ %:== SCY SCR = SFalse+ %:== SCY SCS = SFalse+ %:== SCY SCT = SFalse+ %:== SCY SCU = SFalse+ %:== SCY SCV = SFalse+ %:== SCY SCW = SFalse+ %:== SCY SCX = SFalse+ %:== SCY SCY = STrue+ %:== SCY SCZ = SFalse+ %:== SCZ SCA = SFalse+ %:== SCZ SCB = SFalse+ %:== SCZ SCC = SFalse+ %:== SCZ SCD = SFalse+ %:== SCZ SCE = SFalse+ %:== SCZ SCF = SFalse+ %:== SCZ SCG = SFalse+ %:== SCZ SCH = SFalse+ %:== SCZ SCI = SFalse+ %:== SCZ SCJ = SFalse+ %:== SCZ SCK = SFalse+ %:== SCZ SCL = SFalse+ %:== SCZ SCM = SFalse+ %:== SCZ SCN = SFalse+ %:== SCZ SCO = SFalse+ %:== SCZ SCP = SFalse+ %:== SCZ SCQ = SFalse+ %:== SCZ SCR = SFalse+ %:== SCZ SCS = SFalse+ %:== SCZ SCT = SFalse+ %:== SCZ SCU = SFalse+ %:== SCZ SCV = SFalse+ %:== SCZ SCW = SFalse+ %:== SCZ SCX = SFalse+ %:== SCZ SCY = SFalse+ %:== SCZ SCZ = STrue+ instance SDecide (KProxy :: KProxy AChar) where+ %~ SCA SCA = Proved Refl+ %~ SCA SCB+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCA SCC+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCA SCD+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCA SCE+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCA SCF+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCA SCG+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCA SCH+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCA SCI+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCA SCJ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCA SCK+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCA SCL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCA SCM+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCA SCN+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCA SCO+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCA SCP+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCA SCQ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCA SCR+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCA SCS+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCA SCT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCA SCU+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCA SCV+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCA SCW+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCA SCX+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCA SCY+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCA SCZ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCB SCA+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCB SCB = Proved Refl+ %~ SCB SCC+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCB SCD+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCB SCE+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCB SCF+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCB SCG+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCB SCH+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCB SCI+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCB SCJ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCB SCK+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCB SCL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCB SCM+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCB SCN+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCB SCO+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCB SCP+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCB SCQ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCB SCR+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCB SCS+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCB SCT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCB SCU+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCB SCV+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCB SCW+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCB SCX+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCB SCY+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCB SCZ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCC SCA+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCC SCB+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCC SCC = Proved Refl+ %~ SCC SCD+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCC SCE+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCC SCF+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCC SCG+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCC SCH+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCC SCI+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCC SCJ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCC SCK+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCC SCL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCC SCM+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCC SCN+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCC SCO+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCC SCP+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCC SCQ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCC SCR+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCC SCS+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCC SCT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCC SCU+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCC SCV+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCC SCW+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCC SCX+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCC SCY+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCC SCZ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCD SCA+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCD SCB+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCD SCC+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCD SCD = Proved Refl+ %~ SCD SCE+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCD SCF+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCD SCG+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCD SCH+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCD SCI+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCD SCJ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCD SCK+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCD SCL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCD SCM+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCD SCN+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCD SCO+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCD SCP+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCD SCQ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCD SCR+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCD SCS+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCD SCT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCD SCU+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCD SCV+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCD SCW+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCD SCX+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCD SCY+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCD SCZ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCE SCA+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCE SCB+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCE SCC+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCE SCD+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCE SCE = Proved Refl+ %~ SCE SCF+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCE SCG+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCE SCH+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCE SCI+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCE SCJ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCE SCK+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCE SCL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCE SCM+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCE SCN+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCE SCO+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCE SCP+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCE SCQ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCE SCR+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCE SCS+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCE SCT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCE SCU+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCE SCV+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCE SCW+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCE SCX+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCE SCY+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCE SCZ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCF SCA+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCF SCB+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCF SCC+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCF SCD+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCF SCE+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCF SCF = Proved Refl+ %~ SCF SCG+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCF SCH+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCF SCI+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCF SCJ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCF SCK+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCF SCL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCF SCM+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCF SCN+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCF SCO+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCF SCP+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCF SCQ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCF SCR+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCF SCS+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCF SCT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCF SCU+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCF SCV+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCF SCW+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCF SCX+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCF SCY+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCF SCZ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCG SCA+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCG SCB+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCG SCC+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCG SCD+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCG SCE+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCG SCF+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCG SCG = Proved Refl+ %~ SCG SCH+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCG SCI+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCG SCJ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCG SCK+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCG SCL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCG SCM+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCG SCN+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCG SCO+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCG SCP+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCG SCQ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCG SCR+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCG SCS+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCG SCT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCG SCU+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCG SCV+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCG SCW+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCG SCX+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCG SCY+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCG SCZ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCH SCA+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCH SCB+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCH SCC+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCH SCD+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCH SCE+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCH SCF+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCH SCG+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCH SCH = Proved Refl+ %~ SCH SCI+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCH SCJ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCH SCK+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCH SCL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCH SCM+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCH SCN+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCH SCO+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCH SCP+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCH SCQ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCH SCR+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCH SCS+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCH SCT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCH SCU+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCH SCV+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCH SCW+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCH SCX+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCH SCY+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCH SCZ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCI SCA+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCI SCB+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCI SCC+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCI SCD+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCI SCE+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCI SCF+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCI SCG+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCI SCH+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCI SCI = Proved Refl+ %~ SCI SCJ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCI SCK+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCI SCL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCI SCM+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCI SCN+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCI SCO+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCI SCP+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCI SCQ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCI SCR+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCI SCS+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCI SCT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCI SCU+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCI SCV+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCI SCW+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCI SCX+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCI SCY+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCI SCZ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCJ SCA+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCJ SCB+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCJ SCC+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCJ SCD+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCJ SCE+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCJ SCF+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCJ SCG+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCJ SCH+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCJ SCI+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCJ SCJ = Proved Refl+ %~ SCJ SCK+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCJ SCL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCJ SCM+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCJ SCN+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCJ SCO+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCJ SCP+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCJ SCQ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCJ SCR+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCJ SCS+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCJ SCT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCJ SCU+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCJ SCV+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCJ SCW+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCJ SCX+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCJ SCY+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCJ SCZ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCK SCA+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCK SCB+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCK SCC+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCK SCD+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCK SCE+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCK SCF+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCK SCG+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCK SCH+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCK SCI+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCK SCJ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCK SCK = Proved Refl+ %~ SCK SCL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCK SCM+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCK SCN+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCK SCO+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCK SCP+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCK SCQ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCK SCR+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCK SCS+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCK SCT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCK SCU+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCK SCV+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCK SCW+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCK SCX+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCK SCY+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCK SCZ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCL SCA+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCL SCB+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCL SCC+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCL SCD+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCL SCE+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCL SCF+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCL SCG+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCL SCH+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCL SCI+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCL SCJ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCL SCK+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCL SCL = Proved Refl+ %~ SCL SCM+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCL SCN+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCL SCO+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCL SCP+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCL SCQ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCL SCR+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCL SCS+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCL SCT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCL SCU+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCL SCV+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCL SCW+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCL SCX+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCL SCY+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCL SCZ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCM SCA+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCM SCB+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCM SCC+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCM SCD+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCM SCE+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCM SCF+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCM SCG+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCM SCH+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCM SCI+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCM SCJ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCM SCK+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCM SCL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCM SCM = Proved Refl+ %~ SCM SCN+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCM SCO+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCM SCP+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCM SCQ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCM SCR+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCM SCS+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCM SCT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCM SCU+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCM SCV+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCM SCW+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCM SCX+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCM SCY+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCM SCZ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCN SCA+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCN SCB+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCN SCC+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCN SCD+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCN SCE+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCN SCF+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCN SCG+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCN SCH+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCN SCI+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCN SCJ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCN SCK+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCN SCL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCN SCM+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCN SCN = Proved Refl+ %~ SCN SCO+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCN SCP+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCN SCQ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCN SCR+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCN SCS+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCN SCT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCN SCU+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCN SCV+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCN SCW+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCN SCX+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCN SCY+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCN SCZ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCO SCA+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCO SCB+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCO SCC+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCO SCD+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCO SCE+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCO SCF+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCO SCG+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCO SCH+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCO SCI+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCO SCJ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCO SCK+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCO SCL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCO SCM+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCO SCN+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCO SCO = Proved Refl+ %~ SCO SCP+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCO SCQ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCO SCR+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCO SCS+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCO SCT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCO SCU+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCO SCV+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCO SCW+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCO SCX+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCO SCY+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCO SCZ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCP SCA+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCP SCB+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCP SCC+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCP SCD+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCP SCE+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCP SCF+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCP SCG+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCP SCH+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCP SCI+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCP SCJ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCP SCK+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCP SCL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCP SCM+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCP SCN+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCP SCO+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCP SCP = Proved Refl+ %~ SCP SCQ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCP SCR+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCP SCS+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCP SCT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCP SCU+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCP SCV+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCP SCW+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCP SCX+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCP SCY+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCP SCZ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCQ SCA+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCQ SCB+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCQ SCC+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCQ SCD+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCQ SCE+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCQ SCF+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCQ SCG+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCQ SCH+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCQ SCI+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCQ SCJ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCQ SCK+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCQ SCL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCQ SCM+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCQ SCN+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCQ SCO+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCQ SCP+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCQ SCQ = Proved Refl+ %~ SCQ SCR+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCQ SCS+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCQ SCT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCQ SCU+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCQ SCV+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCQ SCW+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCQ SCX+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCQ SCY+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCQ SCZ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCR SCA+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCR SCB+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCR SCC+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCR SCD+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCR SCE+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCR SCF+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCR SCG+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCR SCH+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCR SCI+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCR SCJ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCR SCK+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCR SCL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCR SCM+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCR SCN+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCR SCO+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCR SCP+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCR SCQ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCR SCR = Proved Refl+ %~ SCR SCS+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCR SCT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCR SCU+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCR SCV+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCR SCW+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCR SCX+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCR SCY+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCR SCZ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCS SCA+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCS SCB+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCS SCC+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCS SCD+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCS SCE+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCS SCF+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCS SCG+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCS SCH+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCS SCI+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCS SCJ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCS SCK+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCS SCL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCS SCM+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCS SCN+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCS SCO+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCS SCP+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCS SCQ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCS SCR+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCS SCS = Proved Refl+ %~ SCS SCT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCS SCU+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCS SCV+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCS SCW+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCS SCX+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCS SCY+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCS SCZ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCT SCA+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCT SCB+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCT SCC+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCT SCD+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCT SCE+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCT SCF+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCT SCG+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCT SCH+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCT SCI+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCT SCJ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCT SCK+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCT SCL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCT SCM+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCT SCN+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCT SCO+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCT SCP+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCT SCQ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCT SCR+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCT SCS+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCT SCT = Proved Refl+ %~ SCT SCU+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCT SCV+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCT SCW+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCT SCX+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCT SCY+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCT SCZ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCU SCA+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCU SCB+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCU SCC+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCU SCD+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCU SCE+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCU SCF+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCU SCG+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCU SCH+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCU SCI+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCU SCJ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCU SCK+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCU SCL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCU SCM+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCU SCN+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCU SCO+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCU SCP+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCU SCQ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCU SCR+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCU SCS+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCU SCT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCU SCU = Proved Refl+ %~ SCU SCV+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCU SCW+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCU SCX+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCU SCY+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCU SCZ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCV SCA+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCV SCB+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCV SCC+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCV SCD+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCV SCE+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCV SCF+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCV SCG+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCV SCH+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCV SCI+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCV SCJ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCV SCK+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCV SCL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCV SCM+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCV SCN+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCV SCO+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCV SCP+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCV SCQ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCV SCR+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCV SCS+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCV SCT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCV SCU+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCV SCV = Proved Refl+ %~ SCV SCW+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCV SCX+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCV SCY+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCV SCZ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCW SCA+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCW SCB+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCW SCC+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCW SCD+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCW SCE+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCW SCF+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCW SCG+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCW SCH+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCW SCI+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCW SCJ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCW SCK+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCW SCL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCW SCM+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCW SCN+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCW SCO+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCW SCP+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCW SCQ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCW SCR+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCW SCS+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCW SCT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCW SCU+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCW SCV+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCW SCW = Proved Refl+ %~ SCW SCX+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCW SCY+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCW SCZ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCX SCA+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCX SCB+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCX SCC+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCX SCD+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCX SCE+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCX SCF+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCX SCG+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCX SCH+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCX SCI+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCX SCJ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCX SCK+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCX SCL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCX SCM+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCX SCN+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCX SCO+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCX SCP+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCX SCQ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCX SCR+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCX SCS+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCX SCT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCX SCU+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCX SCV+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCX SCW+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCX SCX = Proved Refl+ %~ SCX SCY+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCX SCZ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCY SCA+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCY SCB+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCY SCC+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCY SCD+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCY SCE+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCY SCF+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCY SCG+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCY SCH+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCY SCI+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCY SCJ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCY SCK+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCY SCL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCY SCM+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCY SCN+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCY SCO+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCY SCP+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCY SCQ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCY SCR+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCY SCS+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCY SCT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCY SCU+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCY SCV+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCY SCW+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCY SCX+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCY SCY = Proved Refl+ %~ SCY SCZ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCZ SCA+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCZ SCB+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCZ SCC+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCZ SCD+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCZ SCE+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCZ SCF+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCZ SCG+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCZ SCH+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCZ SCI+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCZ SCJ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCZ SCK+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCZ SCL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCZ SCM+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCZ SCN+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCZ SCO+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCZ SCP+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCZ SCQ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCZ SCR+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCZ SCS+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCZ SCT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCZ SCU+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCZ SCV+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCZ SCW+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCZ SCX+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCZ SCY+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SCZ SCZ = Proved Refl+ instance SingI CA where+ sing = SCA+ instance SingI CB where+ sing = SCB+ instance SingI CC where+ sing = SCC+ instance SingI CD where+ sing = SCD+ instance SingI CE where+ sing = SCE+ instance SingI CF where+ sing = SCF+ instance SingI CG where+ sing = SCG+ instance SingI CH where+ sing = SCH+ instance SingI CI where+ sing = SCI+ instance SingI CJ where+ sing = SCJ+ instance SingI CK where+ sing = SCK+ instance SingI CL where+ sing = SCL+ instance SingI CM where+ sing = SCM+ instance SingI CN where+ sing = SCN+ instance SingI CO where+ sing = SCO+ instance SingI CP where+ sing = SCP+ instance SingI CQ where+ sing = SCQ+ instance SingI CR where+ sing = SCR+ instance SingI CS where+ sing = SCS+ instance SingI CT where+ sing = SCT+ instance SingI CU where+ sing = SCU+ instance SingI CV where+ sing = SCV+ instance SingI CW where+ sing = SCW+ instance SingI CX where+ sing = SCX+ instance SingI CY where+ sing = SCY+ instance SingI CZ where+ sing = SCZ+ data instance Sing (z :: Attribute)+ = forall (n :: [AChar]) (n :: U). z ~ Attr n n =>+ SAttr (Sing n) (Sing n)+ type SAttribute (z :: Attribute) = Sing z+ instance SingKind (KProxy :: KProxy Attribute) where+ type instance DemoteRep (KProxy :: KProxy Attribute) = Attribute+ fromSing (SAttr b b) = Attr (fromSing b) (fromSing b)+ toSing (Attr b b)+ = case+ (toSing b :: SomeSing (KProxy :: KProxy [AChar]), + toSing b :: SomeSing (KProxy :: KProxy U))+ of {+ (SomeSing c, SomeSing c) -> SomeSing (SAttr c c) }+ instance (SingI n, SingI n) =>+ SingI (Attr (n :: [AChar]) (n :: U)) where+ sing = SAttr sing sing+ data instance Sing (z :: Schema)+ = forall (n :: [Attribute]). z ~ Sch n => SSch (Sing n)+ type SSchema (z :: Schema) = Sing z+ instance SingKind (KProxy :: KProxy Schema) where+ type instance DemoteRep (KProxy :: KProxy Schema) = Schema+ fromSing (SSch b) = Sch (fromSing b)+ toSing (Sch b)+ = case toSing b :: SomeSing (KProxy :: KProxy [Attribute]) of {+ SomeSing c -> SomeSing (SSch c) }+ instance SingI n => SingI (Sch (n :: [Attribute])) where+ sing = SSch sing+ sAppend ::+ forall (t :: Schema) (t :: Schema).+ Sing t -> Sing t -> Sing (Append t t)+ sAppend (SSch s1) (SSch s2) = SSch ((%:++) s1 s2)+ sAttrNotIn ::+ forall (t :: Attribute) (t :: Schema).+ Sing t -> Sing t -> Sing (AttrNotIn t t)+ sAttrNotIn _ (SSch SNil) = STrue+ sAttrNotIn (SAttr name u) (SSch (SCons (SAttr name' _) t))+ = (%:&&) ((%:/=) name name') (sAttrNotIn (SAttr name u) (SSch t))+ sDisjoint ::+ forall (t :: Schema) (t :: Schema).+ Sing t -> Sing t -> Sing (Disjoint t t)+ sDisjoint (SSch SNil) _ = STrue+ sDisjoint (SSch (SCons h t)) s+ = (%:&&) (sAttrNotIn h s) (sDisjoint (SSch t) s)+ sOccurs ::+ forall (t :: [AChar]) (t :: Schema).+ Sing t -> Sing t -> Sing (Occurs t t)+ sOccurs _ (SSch SNil) = SFalse+ sOccurs name (SSch (SCons (SAttr name' _) attrs))+ = (%:||) ((%:==) name name') (sOccurs name (SSch attrs))+ sLookup ::+ forall (t :: [AChar]) (t :: Schema).+ Sing t -> Sing t -> Sing (Lookup t t)+ sLookup _ (SSch SNil) = undefined+ sLookup name (SSch (SCons (SAttr name' u) attrs))+ = sIf ((%:==) name name') u (sLookup name (SSch attrs))+GradingClient/Database.hs:0:0: Splicing declarations+ return [] ======> GradingClient/Database.hs:0:0:+GradingClient/Database.hs:(0,0)-(0,0): Splicing expression+ cases ''Row [| r |] [| changeId (n ++ (getId r)) r |]+ ======>+ case r of {+ EmptyRow _ -> changeId (n ++ (getId r)) r+ ConsRow _ _ -> changeId (n ++ (getId r)) r }
+ tests/compile-and-dump/GradingClient/Database.ghc78.template view
@@ -0,0 +1,3812 @@+GradingClient/Database.hs:0:0: Splicing declarations+ singletons+ [d| data Nat+ = Zero | Succ Nat+ deriving (Eq, Ord) |]+ ======>+ GradingClient/Database.hs:(0,0)-(0,0)+ data Nat+ = Zero | Succ Nat+ deriving (Eq, Ord)+ type family Equals_0123456789 (a :: Nat) (b :: Nat) :: Bool where+ Equals_0123456789 Zero Zero = True+ Equals_0123456789 (Succ a) (Succ b) = (==) a b+ Equals_0123456789 (a :: Nat) (b :: Nat) = False+ type instance (==) (a :: Nat) (b :: Nat) = Equals_0123456789 a b+ data instance Sing (z :: Nat)+ = z ~ Zero => SZero |+ forall (n :: Nat). z ~ Succ n => SSucc (Sing n)+ type SNat (z :: Nat) = Sing z+ instance SingKind (KProxy :: KProxy Nat) where+ type DemoteRep (KProxy :: KProxy Nat) = Nat+ fromSing SZero = Zero+ fromSing (SSucc b) = Succ (fromSing b)+ toSing Zero = SomeSing SZero+ toSing (Succ b)+ = case toSing b :: SomeSing (KProxy :: KProxy Nat) of {+ SomeSing c -> SomeSing (SSucc c) }+ instance SEq (KProxy :: KProxy Nat) where+ (%:==) SZero SZero = STrue+ (%:==) SZero (SSucc _) = SFalse+ (%:==) (SSucc _) SZero = SFalse+ (%:==) (SSucc a) (SSucc b) = (%:==) a b+ instance SDecide (KProxy :: KProxy Nat) where+ (%~) SZero SZero = Proved Refl+ (%~) SZero (SSucc _)+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) (SSucc _) SZero+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) (SSucc a) (SSucc b)+ = case (%~) a b of {+ Proved Refl -> Proved Refl+ Disproved contra -> Disproved (\ Refl -> contra Refl) }+ instance SingI Zero where+ sing = SZero+ instance SingI n => SingI (Succ (n :: Nat)) where+ sing = SSucc sing+GradingClient/Database.hs:0:0: Splicing declarations+ singletons+ [d| append :: Schema -> Schema -> Schema+ append (Sch s1) (Sch s2) = Sch (s1 ++ s2)+ attrNotIn :: Attribute -> Schema -> Bool+ attrNotIn _ (Sch []) = True+ attrNotIn (Attr name u) (Sch ((Attr name' _) : t))+ = (name /= name') && (attrNotIn (Attr name u) (Sch t))+ disjoint :: Schema -> Schema -> Bool+ disjoint (Sch []) _ = True+ disjoint (Sch (h : t)) s = (attrNotIn h s) && (disjoint (Sch t) s)+ occurs :: [AChar] -> Schema -> Bool+ occurs _ (Sch []) = False+ occurs name (Sch ((Attr name' _) : attrs))+ = name == name' || occurs name (Sch attrs)+ lookup :: [AChar] -> Schema -> U+ lookup _ (Sch []) = undefined+ lookup name (Sch ((Attr name' u) : attrs))+ = if name == name' then u else lookup name (Sch attrs)+ + data U+ = BOOL | STRING | NAT | VEC U Nat+ deriving (Read, Eq, Show)+ data AChar+ = CA |+ CB |+ CC |+ CD |+ CE |+ CF |+ CG |+ CH |+ CI |+ CJ |+ CK |+ CL |+ CM |+ CN |+ CO |+ CP |+ CQ |+ CR |+ CS |+ CT |+ CU |+ CV |+ CW |+ CX |+ CY |+ CZ+ deriving (Read, Show, Eq)+ data Attribute = Attr [AChar] U+ data Schema = Sch [Attribute] |]+ ======>+ GradingClient/Database.hs:(0,0)-(0,0)+ data U+ = BOOL | STRING | NAT | VEC U Nat+ deriving (Read, Eq, Show)+ data AChar+ = CA |+ CB |+ CC |+ CD |+ CE |+ CF |+ CG |+ CH |+ CI |+ CJ |+ CK |+ CL |+ CM |+ CN |+ CO |+ CP |+ CQ |+ CR |+ CS |+ CT |+ CU |+ CV |+ CW |+ CX |+ CY |+ CZ+ deriving (Read, Show, Eq)+ data Attribute = Attr [AChar] U+ data Schema = Sch [Attribute]+ append :: Schema -> Schema -> Schema+ append (Sch s1) (Sch s2) = Sch (s1 ++ s2)+ attrNotIn :: Attribute -> Schema -> Bool+ attrNotIn _ (Sch GHC.Types.[]) = True+ attrNotIn (Attr name u) (Sch ((Attr name' _) GHC.Types.: t))+ = ((name /= name') && (attrNotIn (Attr name u) (Sch t)))+ disjoint :: Schema -> Schema -> Bool+ disjoint (Sch GHC.Types.[]) _ = True+ disjoint (Sch (h GHC.Types.: t)) s+ = ((attrNotIn h s) && (disjoint (Sch t) s))+ occurs :: [AChar] -> Schema -> Bool+ occurs _ (Sch GHC.Types.[]) = False+ occurs name (Sch ((Attr name' _) GHC.Types.: attrs))+ = ((name == name') || (occurs name (Sch attrs)))+ lookup :: [AChar] -> Schema -> U+ lookup _ (Sch GHC.Types.[]) = undefined+ lookup name (Sch ((Attr name' u) GHC.Types.: attrs))+ = if (name == name') then u else lookup name (Sch attrs)+ type family Equals_0123456789 (a :: U) (b :: U) :: Bool where+ Equals_0123456789 BOOL BOOL = True+ Equals_0123456789 STRING STRING = True+ Equals_0123456789 NAT NAT = True+ Equals_0123456789 (VEC a a) (VEC b b) = (:&&) ((==) a b) ((==) a b)+ Equals_0123456789 (a :: U) (b :: U) = False+ type instance (==) (a :: U) (b :: U) = Equals_0123456789 a b+ type family Equals_0123456789 (a :: AChar)+ (b :: AChar) :: Bool where+ Equals_0123456789 CA CA = True+ Equals_0123456789 CB CB = True+ Equals_0123456789 CC CC = True+ Equals_0123456789 CD CD = True+ Equals_0123456789 CE CE = True+ Equals_0123456789 CF CF = True+ Equals_0123456789 CG CG = True+ Equals_0123456789 CH CH = True+ Equals_0123456789 CI CI = True+ Equals_0123456789 CJ CJ = True+ Equals_0123456789 CK CK = True+ Equals_0123456789 CL CL = True+ Equals_0123456789 CM CM = True+ Equals_0123456789 CN CN = True+ Equals_0123456789 CO CO = True+ Equals_0123456789 CP CP = True+ Equals_0123456789 CQ CQ = True+ Equals_0123456789 CR CR = True+ Equals_0123456789 CS CS = True+ Equals_0123456789 CT CT = True+ Equals_0123456789 CU CU = True+ Equals_0123456789 CV CV = True+ Equals_0123456789 CW CW = True+ Equals_0123456789 CX CX = True+ Equals_0123456789 CY CY = True+ Equals_0123456789 CZ CZ = True+ Equals_0123456789 (a :: AChar) (b :: AChar) = False+ type instance (==) (a :: AChar) (b :: AChar) = Equals_0123456789 a b+ type family Append (a :: Schema) (a :: Schema) :: Schema where+ Append (Sch s1) (Sch s2) = Sch ((:++) s1 s2)+ type family AttrNotIn (a :: Attribute) (a :: Schema) :: Bool where+ AttrNotIn z (Sch GHC.Types.[]) = True+ AttrNotIn (Attr name u) (Sch ((GHC.Types.:) (Attr name' z) t)) = (:&&) ((:/=) name name') (AttrNotIn (Attr name u) (Sch t))+ type family Disjoint (a :: Schema) (a :: Schema) :: Bool where+ Disjoint (Sch GHC.Types.[]) z = True+ Disjoint (Sch ((GHC.Types.:) h t)) s = (:&&) (AttrNotIn h s) (Disjoint (Sch t) s)+ type family Occurs (a :: [AChar]) (a :: Schema) :: Bool where+ Occurs z (Sch GHC.Types.[]) = False+ Occurs name (Sch ((GHC.Types.:) (Attr name' z) attrs)) = (:||) ((:==) name name') (Occurs name (Sch attrs))+ type family Lookup (a :: [AChar]) (a :: Schema) :: U where+ Lookup z (Sch GHC.Types.[]) = Any+ Lookup name (Sch ((GHC.Types.:) (Attr name' u) attrs)) = If ((:==) name name') u (Lookup name (Sch attrs))+ data instance Sing (z :: U)+ = z ~ BOOL => SBOOL |+ z ~ STRING => SSTRING |+ z ~ NAT => SNAT |+ forall (n :: U) (n :: Nat). z ~ VEC n n => SVEC (Sing n) (Sing n)+ type SU (z :: U) = Sing z+ instance SingKind (KProxy :: KProxy U) where+ type DemoteRep (KProxy :: KProxy U) = U+ fromSing SBOOL = BOOL+ fromSing SSTRING = STRING+ fromSing SNAT = NAT+ fromSing (SVEC b b) = VEC (fromSing b) (fromSing b)+ toSing BOOL = SomeSing SBOOL+ toSing STRING = SomeSing SSTRING+ toSing NAT = SomeSing SNAT+ toSing (VEC b b)+ = case+ (toSing b :: SomeSing (KProxy :: KProxy U), + toSing b :: SomeSing (KProxy :: KProxy Nat))+ of {+ (SomeSing c, SomeSing c) -> SomeSing (SVEC c c) }+ instance SEq (KProxy :: KProxy U) where+ (%:==) SBOOL SBOOL = STrue+ (%:==) SBOOL SSTRING = SFalse+ (%:==) SBOOL SNAT = SFalse+ (%:==) SBOOL (SVEC _ _) = SFalse+ (%:==) SSTRING SBOOL = SFalse+ (%:==) SSTRING SSTRING = STrue+ (%:==) SSTRING SNAT = SFalse+ (%:==) SSTRING (SVEC _ _) = SFalse+ (%:==) SNAT SBOOL = SFalse+ (%:==) SNAT SSTRING = SFalse+ (%:==) SNAT SNAT = STrue+ (%:==) SNAT (SVEC _ _) = SFalse+ (%:==) (SVEC _ _) SBOOL = SFalse+ (%:==) (SVEC _ _) SSTRING = SFalse+ (%:==) (SVEC _ _) SNAT = SFalse+ (%:==) (SVEC a a) (SVEC b b) = (%:&&) ((%:==) a b) ((%:==) a b)+ instance SDecide (KProxy :: KProxy U) where+ (%~) SBOOL SBOOL = Proved Refl+ (%~) SBOOL SSTRING+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SBOOL SNAT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SBOOL (SVEC _ _)+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SSTRING SBOOL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SSTRING SSTRING = Proved Refl+ (%~) SSTRING SNAT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SSTRING (SVEC _ _)+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SNAT SBOOL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SNAT SSTRING+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SNAT SNAT = Proved Refl+ (%~) SNAT (SVEC _ _)+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) (SVEC _ _) SBOOL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) (SVEC _ _) SSTRING+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) (SVEC _ _) SNAT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) (SVEC a a) (SVEC b b)+ = case ((%~) a b, (%~) a b) of {+ (Proved Refl, Proved Refl) -> Proved Refl+ (Disproved contra, _) -> Disproved (\ Refl -> contra Refl)+ (_, Disproved contra) -> Disproved (\ Refl -> contra Refl) }+ instance SingI BOOL where+ sing = SBOOL+ instance SingI STRING where+ sing = SSTRING+ instance SingI NAT where+ sing = SNAT+ instance (SingI n, SingI n) =>+ SingI (VEC (n :: U) (n :: Nat)) where+ sing = SVEC sing sing+ data instance Sing (z :: AChar)+ = z ~ CA => SCA |+ z ~ CB => SCB |+ z ~ CC => SCC |+ z ~ CD => SCD |+ z ~ CE => SCE |+ z ~ CF => SCF |+ z ~ CG => SCG |+ z ~ CH => SCH |+ z ~ CI => SCI |+ z ~ CJ => SCJ |+ z ~ CK => SCK |+ z ~ CL => SCL |+ z ~ CM => SCM |+ z ~ CN => SCN |+ z ~ CO => SCO |+ z ~ CP => SCP |+ z ~ CQ => SCQ |+ z ~ CR => SCR |+ z ~ CS => SCS |+ z ~ CT => SCT |+ z ~ CU => SCU |+ z ~ CV => SCV |+ z ~ CW => SCW |+ z ~ CX => SCX |+ z ~ CY => SCY |+ z ~ CZ => SCZ+ type SAChar (z :: AChar) = Sing z+ instance SingKind (KProxy :: KProxy AChar) where+ type DemoteRep (KProxy :: KProxy AChar) = AChar+ fromSing SCA = CA+ fromSing SCB = CB+ fromSing SCC = CC+ fromSing SCD = CD+ fromSing SCE = CE+ fromSing SCF = CF+ fromSing SCG = CG+ fromSing SCH = CH+ fromSing SCI = CI+ fromSing SCJ = CJ+ fromSing SCK = CK+ fromSing SCL = CL+ fromSing SCM = CM+ fromSing SCN = CN+ fromSing SCO = CO+ fromSing SCP = CP+ fromSing SCQ = CQ+ fromSing SCR = CR+ fromSing SCS = CS+ fromSing SCT = CT+ fromSing SCU = CU+ fromSing SCV = CV+ fromSing SCW = CW+ fromSing SCX = CX+ fromSing SCY = CY+ fromSing SCZ = CZ+ toSing CA = SomeSing SCA+ toSing CB = SomeSing SCB+ toSing CC = SomeSing SCC+ toSing CD = SomeSing SCD+ toSing CE = SomeSing SCE+ toSing CF = SomeSing SCF+ toSing CG = SomeSing SCG+ toSing CH = SomeSing SCH+ toSing CI = SomeSing SCI+ toSing CJ = SomeSing SCJ+ toSing CK = SomeSing SCK+ toSing CL = SomeSing SCL+ toSing CM = SomeSing SCM+ toSing CN = SomeSing SCN+ toSing CO = SomeSing SCO+ toSing CP = SomeSing SCP+ toSing CQ = SomeSing SCQ+ toSing CR = SomeSing SCR+ toSing CS = SomeSing SCS+ toSing CT = SomeSing SCT+ toSing CU = SomeSing SCU+ toSing CV = SomeSing SCV+ toSing CW = SomeSing SCW+ toSing CX = SomeSing SCX+ toSing CY = SomeSing SCY+ toSing CZ = SomeSing SCZ+ instance SEq (KProxy :: KProxy AChar) where+ (%:==) SCA SCA = STrue+ (%:==) SCA SCB = SFalse+ (%:==) SCA SCC = SFalse+ (%:==) SCA SCD = SFalse+ (%:==) SCA SCE = SFalse+ (%:==) SCA SCF = SFalse+ (%:==) SCA SCG = SFalse+ (%:==) SCA SCH = SFalse+ (%:==) SCA SCI = SFalse+ (%:==) SCA SCJ = SFalse+ (%:==) SCA SCK = SFalse+ (%:==) SCA SCL = SFalse+ (%:==) SCA SCM = SFalse+ (%:==) SCA SCN = SFalse+ (%:==) SCA SCO = SFalse+ (%:==) SCA SCP = SFalse+ (%:==) SCA SCQ = SFalse+ (%:==) SCA SCR = SFalse+ (%:==) SCA SCS = SFalse+ (%:==) SCA SCT = SFalse+ (%:==) SCA SCU = SFalse+ (%:==) SCA SCV = SFalse+ (%:==) SCA SCW = SFalse+ (%:==) SCA SCX = SFalse+ (%:==) SCA SCY = SFalse+ (%:==) SCA SCZ = SFalse+ (%:==) SCB SCA = SFalse+ (%:==) SCB SCB = STrue+ (%:==) SCB SCC = SFalse+ (%:==) SCB SCD = SFalse+ (%:==) SCB SCE = SFalse+ (%:==) SCB SCF = SFalse+ (%:==) SCB SCG = SFalse+ (%:==) SCB SCH = SFalse+ (%:==) SCB SCI = SFalse+ (%:==) SCB SCJ = SFalse+ (%:==) SCB SCK = SFalse+ (%:==) SCB SCL = SFalse+ (%:==) SCB SCM = SFalse+ (%:==) SCB SCN = SFalse+ (%:==) SCB SCO = SFalse+ (%:==) SCB SCP = SFalse+ (%:==) SCB SCQ = SFalse+ (%:==) SCB SCR = SFalse+ (%:==) SCB SCS = SFalse+ (%:==) SCB SCT = SFalse+ (%:==) SCB SCU = SFalse+ (%:==) SCB SCV = SFalse+ (%:==) SCB SCW = SFalse+ (%:==) SCB SCX = SFalse+ (%:==) SCB SCY = SFalse+ (%:==) SCB SCZ = SFalse+ (%:==) SCC SCA = SFalse+ (%:==) SCC SCB = SFalse+ (%:==) SCC SCC = STrue+ (%:==) SCC SCD = SFalse+ (%:==) SCC SCE = SFalse+ (%:==) SCC SCF = SFalse+ (%:==) SCC SCG = SFalse+ (%:==) SCC SCH = SFalse+ (%:==) SCC SCI = SFalse+ (%:==) SCC SCJ = SFalse+ (%:==) SCC SCK = SFalse+ (%:==) SCC SCL = SFalse+ (%:==) SCC SCM = SFalse+ (%:==) SCC SCN = SFalse+ (%:==) SCC SCO = SFalse+ (%:==) SCC SCP = SFalse+ (%:==) SCC SCQ = SFalse+ (%:==) SCC SCR = SFalse+ (%:==) SCC SCS = SFalse+ (%:==) SCC SCT = SFalse+ (%:==) SCC SCU = SFalse+ (%:==) SCC SCV = SFalse+ (%:==) SCC SCW = SFalse+ (%:==) SCC SCX = SFalse+ (%:==) SCC SCY = SFalse+ (%:==) SCC SCZ = SFalse+ (%:==) SCD SCA = SFalse+ (%:==) SCD SCB = SFalse+ (%:==) SCD SCC = SFalse+ (%:==) SCD SCD = STrue+ (%:==) SCD SCE = SFalse+ (%:==) SCD SCF = SFalse+ (%:==) SCD SCG = SFalse+ (%:==) SCD SCH = SFalse+ (%:==) SCD SCI = SFalse+ (%:==) SCD SCJ = SFalse+ (%:==) SCD SCK = SFalse+ (%:==) SCD SCL = SFalse+ (%:==) SCD SCM = SFalse+ (%:==) SCD SCN = SFalse+ (%:==) SCD SCO = SFalse+ (%:==) SCD SCP = SFalse+ (%:==) SCD SCQ = SFalse+ (%:==) SCD SCR = SFalse+ (%:==) SCD SCS = SFalse+ (%:==) SCD SCT = SFalse+ (%:==) SCD SCU = SFalse+ (%:==) SCD SCV = SFalse+ (%:==) SCD SCW = SFalse+ (%:==) SCD SCX = SFalse+ (%:==) SCD SCY = SFalse+ (%:==) SCD SCZ = SFalse+ (%:==) SCE SCA = SFalse+ (%:==) SCE SCB = SFalse+ (%:==) SCE SCC = SFalse+ (%:==) SCE SCD = SFalse+ (%:==) SCE SCE = STrue+ (%:==) SCE SCF = SFalse+ (%:==) SCE SCG = SFalse+ (%:==) SCE SCH = SFalse+ (%:==) SCE SCI = SFalse+ (%:==) SCE SCJ = SFalse+ (%:==) SCE SCK = SFalse+ (%:==) SCE SCL = SFalse+ (%:==) SCE SCM = SFalse+ (%:==) SCE SCN = SFalse+ (%:==) SCE SCO = SFalse+ (%:==) SCE SCP = SFalse+ (%:==) SCE SCQ = SFalse+ (%:==) SCE SCR = SFalse+ (%:==) SCE SCS = SFalse+ (%:==) SCE SCT = SFalse+ (%:==) SCE SCU = SFalse+ (%:==) SCE SCV = SFalse+ (%:==) SCE SCW = SFalse+ (%:==) SCE SCX = SFalse+ (%:==) SCE SCY = SFalse+ (%:==) SCE SCZ = SFalse+ (%:==) SCF SCA = SFalse+ (%:==) SCF SCB = SFalse+ (%:==) SCF SCC = SFalse+ (%:==) SCF SCD = SFalse+ (%:==) SCF SCE = SFalse+ (%:==) SCF SCF = STrue+ (%:==) SCF SCG = SFalse+ (%:==) SCF SCH = SFalse+ (%:==) SCF SCI = SFalse+ (%:==) SCF SCJ = SFalse+ (%:==) SCF SCK = SFalse+ (%:==) SCF SCL = SFalse+ (%:==) SCF SCM = SFalse+ (%:==) SCF SCN = SFalse+ (%:==) SCF SCO = SFalse+ (%:==) SCF SCP = SFalse+ (%:==) SCF SCQ = SFalse+ (%:==) SCF SCR = SFalse+ (%:==) SCF SCS = SFalse+ (%:==) SCF SCT = SFalse+ (%:==) SCF SCU = SFalse+ (%:==) SCF SCV = SFalse+ (%:==) SCF SCW = SFalse+ (%:==) SCF SCX = SFalse+ (%:==) SCF SCY = SFalse+ (%:==) SCF SCZ = SFalse+ (%:==) SCG SCA = SFalse+ (%:==) SCG SCB = SFalse+ (%:==) SCG SCC = SFalse+ (%:==) SCG SCD = SFalse+ (%:==) SCG SCE = SFalse+ (%:==) SCG SCF = SFalse+ (%:==) SCG SCG = STrue+ (%:==) SCG SCH = SFalse+ (%:==) SCG SCI = SFalse+ (%:==) SCG SCJ = SFalse+ (%:==) SCG SCK = SFalse+ (%:==) SCG SCL = SFalse+ (%:==) SCG SCM = SFalse+ (%:==) SCG SCN = SFalse+ (%:==) SCG SCO = SFalse+ (%:==) SCG SCP = SFalse+ (%:==) SCG SCQ = SFalse+ (%:==) SCG SCR = SFalse+ (%:==) SCG SCS = SFalse+ (%:==) SCG SCT = SFalse+ (%:==) SCG SCU = SFalse+ (%:==) SCG SCV = SFalse+ (%:==) SCG SCW = SFalse+ (%:==) SCG SCX = SFalse+ (%:==) SCG SCY = SFalse+ (%:==) SCG SCZ = SFalse+ (%:==) SCH SCA = SFalse+ (%:==) SCH SCB = SFalse+ (%:==) SCH SCC = SFalse+ (%:==) SCH SCD = SFalse+ (%:==) SCH SCE = SFalse+ (%:==) SCH SCF = SFalse+ (%:==) SCH SCG = SFalse+ (%:==) SCH SCH = STrue+ (%:==) SCH SCI = SFalse+ (%:==) SCH SCJ = SFalse+ (%:==) SCH SCK = SFalse+ (%:==) SCH SCL = SFalse+ (%:==) SCH SCM = SFalse+ (%:==) SCH SCN = SFalse+ (%:==) SCH SCO = SFalse+ (%:==) SCH SCP = SFalse+ (%:==) SCH SCQ = SFalse+ (%:==) SCH SCR = SFalse+ (%:==) SCH SCS = SFalse+ (%:==) SCH SCT = SFalse+ (%:==) SCH SCU = SFalse+ (%:==) SCH SCV = SFalse+ (%:==) SCH SCW = SFalse+ (%:==) SCH SCX = SFalse+ (%:==) SCH SCY = SFalse+ (%:==) SCH SCZ = SFalse+ (%:==) SCI SCA = SFalse+ (%:==) SCI SCB = SFalse+ (%:==) SCI SCC = SFalse+ (%:==) SCI SCD = SFalse+ (%:==) SCI SCE = SFalse+ (%:==) SCI SCF = SFalse+ (%:==) SCI SCG = SFalse+ (%:==) SCI SCH = SFalse+ (%:==) SCI SCI = STrue+ (%:==) SCI SCJ = SFalse+ (%:==) SCI SCK = SFalse+ (%:==) SCI SCL = SFalse+ (%:==) SCI SCM = SFalse+ (%:==) SCI SCN = SFalse+ (%:==) SCI SCO = SFalse+ (%:==) SCI SCP = SFalse+ (%:==) SCI SCQ = SFalse+ (%:==) SCI SCR = SFalse+ (%:==) SCI SCS = SFalse+ (%:==) SCI SCT = SFalse+ (%:==) SCI SCU = SFalse+ (%:==) SCI SCV = SFalse+ (%:==) SCI SCW = SFalse+ (%:==) SCI SCX = SFalse+ (%:==) SCI SCY = SFalse+ (%:==) SCI SCZ = SFalse+ (%:==) SCJ SCA = SFalse+ (%:==) SCJ SCB = SFalse+ (%:==) SCJ SCC = SFalse+ (%:==) SCJ SCD = SFalse+ (%:==) SCJ SCE = SFalse+ (%:==) SCJ SCF = SFalse+ (%:==) SCJ SCG = SFalse+ (%:==) SCJ SCH = SFalse+ (%:==) SCJ SCI = SFalse+ (%:==) SCJ SCJ = STrue+ (%:==) SCJ SCK = SFalse+ (%:==) SCJ SCL = SFalse+ (%:==) SCJ SCM = SFalse+ (%:==) SCJ SCN = SFalse+ (%:==) SCJ SCO = SFalse+ (%:==) SCJ SCP = SFalse+ (%:==) SCJ SCQ = SFalse+ (%:==) SCJ SCR = SFalse+ (%:==) SCJ SCS = SFalse+ (%:==) SCJ SCT = SFalse+ (%:==) SCJ SCU = SFalse+ (%:==) SCJ SCV = SFalse+ (%:==) SCJ SCW = SFalse+ (%:==) SCJ SCX = SFalse+ (%:==) SCJ SCY = SFalse+ (%:==) SCJ SCZ = SFalse+ (%:==) SCK SCA = SFalse+ (%:==) SCK SCB = SFalse+ (%:==) SCK SCC = SFalse+ (%:==) SCK SCD = SFalse+ (%:==) SCK SCE = SFalse+ (%:==) SCK SCF = SFalse+ (%:==) SCK SCG = SFalse+ (%:==) SCK SCH = SFalse+ (%:==) SCK SCI = SFalse+ (%:==) SCK SCJ = SFalse+ (%:==) SCK SCK = STrue+ (%:==) SCK SCL = SFalse+ (%:==) SCK SCM = SFalse+ (%:==) SCK SCN = SFalse+ (%:==) SCK SCO = SFalse+ (%:==) SCK SCP = SFalse+ (%:==) SCK SCQ = SFalse+ (%:==) SCK SCR = SFalse+ (%:==) SCK SCS = SFalse+ (%:==) SCK SCT = SFalse+ (%:==) SCK SCU = SFalse+ (%:==) SCK SCV = SFalse+ (%:==) SCK SCW = SFalse+ (%:==) SCK SCX = SFalse+ (%:==) SCK SCY = SFalse+ (%:==) SCK SCZ = SFalse+ (%:==) SCL SCA = SFalse+ (%:==) SCL SCB = SFalse+ (%:==) SCL SCC = SFalse+ (%:==) SCL SCD = SFalse+ (%:==) SCL SCE = SFalse+ (%:==) SCL SCF = SFalse+ (%:==) SCL SCG = SFalse+ (%:==) SCL SCH = SFalse+ (%:==) SCL SCI = SFalse+ (%:==) SCL SCJ = SFalse+ (%:==) SCL SCK = SFalse+ (%:==) SCL SCL = STrue+ (%:==) SCL SCM = SFalse+ (%:==) SCL SCN = SFalse+ (%:==) SCL SCO = SFalse+ (%:==) SCL SCP = SFalse+ (%:==) SCL SCQ = SFalse+ (%:==) SCL SCR = SFalse+ (%:==) SCL SCS = SFalse+ (%:==) SCL SCT = SFalse+ (%:==) SCL SCU = SFalse+ (%:==) SCL SCV = SFalse+ (%:==) SCL SCW = SFalse+ (%:==) SCL SCX = SFalse+ (%:==) SCL SCY = SFalse+ (%:==) SCL SCZ = SFalse+ (%:==) SCM SCA = SFalse+ (%:==) SCM SCB = SFalse+ (%:==) SCM SCC = SFalse+ (%:==) SCM SCD = SFalse+ (%:==) SCM SCE = SFalse+ (%:==) SCM SCF = SFalse+ (%:==) SCM SCG = SFalse+ (%:==) SCM SCH = SFalse+ (%:==) SCM SCI = SFalse+ (%:==) SCM SCJ = SFalse+ (%:==) SCM SCK = SFalse+ (%:==) SCM SCL = SFalse+ (%:==) SCM SCM = STrue+ (%:==) SCM SCN = SFalse+ (%:==) SCM SCO = SFalse+ (%:==) SCM SCP = SFalse+ (%:==) SCM SCQ = SFalse+ (%:==) SCM SCR = SFalse+ (%:==) SCM SCS = SFalse+ (%:==) SCM SCT = SFalse+ (%:==) SCM SCU = SFalse+ (%:==) SCM SCV = SFalse+ (%:==) SCM SCW = SFalse+ (%:==) SCM SCX = SFalse+ (%:==) SCM SCY = SFalse+ (%:==) SCM SCZ = SFalse+ (%:==) SCN SCA = SFalse+ (%:==) SCN SCB = SFalse+ (%:==) SCN SCC = SFalse+ (%:==) SCN SCD = SFalse+ (%:==) SCN SCE = SFalse+ (%:==) SCN SCF = SFalse+ (%:==) SCN SCG = SFalse+ (%:==) SCN SCH = SFalse+ (%:==) SCN SCI = SFalse+ (%:==) SCN SCJ = SFalse+ (%:==) SCN SCK = SFalse+ (%:==) SCN SCL = SFalse+ (%:==) SCN SCM = SFalse+ (%:==) SCN SCN = STrue+ (%:==) SCN SCO = SFalse+ (%:==) SCN SCP = SFalse+ (%:==) SCN SCQ = SFalse+ (%:==) SCN SCR = SFalse+ (%:==) SCN SCS = SFalse+ (%:==) SCN SCT = SFalse+ (%:==) SCN SCU = SFalse+ (%:==) SCN SCV = SFalse+ (%:==) SCN SCW = SFalse+ (%:==) SCN SCX = SFalse+ (%:==) SCN SCY = SFalse+ (%:==) SCN SCZ = SFalse+ (%:==) SCO SCA = SFalse+ (%:==) SCO SCB = SFalse+ (%:==) SCO SCC = SFalse+ (%:==) SCO SCD = SFalse+ (%:==) SCO SCE = SFalse+ (%:==) SCO SCF = SFalse+ (%:==) SCO SCG = SFalse+ (%:==) SCO SCH = SFalse+ (%:==) SCO SCI = SFalse+ (%:==) SCO SCJ = SFalse+ (%:==) SCO SCK = SFalse+ (%:==) SCO SCL = SFalse+ (%:==) SCO SCM = SFalse+ (%:==) SCO SCN = SFalse+ (%:==) SCO SCO = STrue+ (%:==) SCO SCP = SFalse+ (%:==) SCO SCQ = SFalse+ (%:==) SCO SCR = SFalse+ (%:==) SCO SCS = SFalse+ (%:==) SCO SCT = SFalse+ (%:==) SCO SCU = SFalse+ (%:==) SCO SCV = SFalse+ (%:==) SCO SCW = SFalse+ (%:==) SCO SCX = SFalse+ (%:==) SCO SCY = SFalse+ (%:==) SCO SCZ = SFalse+ (%:==) SCP SCA = SFalse+ (%:==) SCP SCB = SFalse+ (%:==) SCP SCC = SFalse+ (%:==) SCP SCD = SFalse+ (%:==) SCP SCE = SFalse+ (%:==) SCP SCF = SFalse+ (%:==) SCP SCG = SFalse+ (%:==) SCP SCH = SFalse+ (%:==) SCP SCI = SFalse+ (%:==) SCP SCJ = SFalse+ (%:==) SCP SCK = SFalse+ (%:==) SCP SCL = SFalse+ (%:==) SCP SCM = SFalse+ (%:==) SCP SCN = SFalse+ (%:==) SCP SCO = SFalse+ (%:==) SCP SCP = STrue+ (%:==) SCP SCQ = SFalse+ (%:==) SCP SCR = SFalse+ (%:==) SCP SCS = SFalse+ (%:==) SCP SCT = SFalse+ (%:==) SCP SCU = SFalse+ (%:==) SCP SCV = SFalse+ (%:==) SCP SCW = SFalse+ (%:==) SCP SCX = SFalse+ (%:==) SCP SCY = SFalse+ (%:==) SCP SCZ = SFalse+ (%:==) SCQ SCA = SFalse+ (%:==) SCQ SCB = SFalse+ (%:==) SCQ SCC = SFalse+ (%:==) SCQ SCD = SFalse+ (%:==) SCQ SCE = SFalse+ (%:==) SCQ SCF = SFalse+ (%:==) SCQ SCG = SFalse+ (%:==) SCQ SCH = SFalse+ (%:==) SCQ SCI = SFalse+ (%:==) SCQ SCJ = SFalse+ (%:==) SCQ SCK = SFalse+ (%:==) SCQ SCL = SFalse+ (%:==) SCQ SCM = SFalse+ (%:==) SCQ SCN = SFalse+ (%:==) SCQ SCO = SFalse+ (%:==) SCQ SCP = SFalse+ (%:==) SCQ SCQ = STrue+ (%:==) SCQ SCR = SFalse+ (%:==) SCQ SCS = SFalse+ (%:==) SCQ SCT = SFalse+ (%:==) SCQ SCU = SFalse+ (%:==) SCQ SCV = SFalse+ (%:==) SCQ SCW = SFalse+ (%:==) SCQ SCX = SFalse+ (%:==) SCQ SCY = SFalse+ (%:==) SCQ SCZ = SFalse+ (%:==) SCR SCA = SFalse+ (%:==) SCR SCB = SFalse+ (%:==) SCR SCC = SFalse+ (%:==) SCR SCD = SFalse+ (%:==) SCR SCE = SFalse+ (%:==) SCR SCF = SFalse+ (%:==) SCR SCG = SFalse+ (%:==) SCR SCH = SFalse+ (%:==) SCR SCI = SFalse+ (%:==) SCR SCJ = SFalse+ (%:==) SCR SCK = SFalse+ (%:==) SCR SCL = SFalse+ (%:==) SCR SCM = SFalse+ (%:==) SCR SCN = SFalse+ (%:==) SCR SCO = SFalse+ (%:==) SCR SCP = SFalse+ (%:==) SCR SCQ = SFalse+ (%:==) SCR SCR = STrue+ (%:==) SCR SCS = SFalse+ (%:==) SCR SCT = SFalse+ (%:==) SCR SCU = SFalse+ (%:==) SCR SCV = SFalse+ (%:==) SCR SCW = SFalse+ (%:==) SCR SCX = SFalse+ (%:==) SCR SCY = SFalse+ (%:==) SCR SCZ = SFalse+ (%:==) SCS SCA = SFalse+ (%:==) SCS SCB = SFalse+ (%:==) SCS SCC = SFalse+ (%:==) SCS SCD = SFalse+ (%:==) SCS SCE = SFalse+ (%:==) SCS SCF = SFalse+ (%:==) SCS SCG = SFalse+ (%:==) SCS SCH = SFalse+ (%:==) SCS SCI = SFalse+ (%:==) SCS SCJ = SFalse+ (%:==) SCS SCK = SFalse+ (%:==) SCS SCL = SFalse+ (%:==) SCS SCM = SFalse+ (%:==) SCS SCN = SFalse+ (%:==) SCS SCO = SFalse+ (%:==) SCS SCP = SFalse+ (%:==) SCS SCQ = SFalse+ (%:==) SCS SCR = SFalse+ (%:==) SCS SCS = STrue+ (%:==) SCS SCT = SFalse+ (%:==) SCS SCU = SFalse+ (%:==) SCS SCV = SFalse+ (%:==) SCS SCW = SFalse+ (%:==) SCS SCX = SFalse+ (%:==) SCS SCY = SFalse+ (%:==) SCS SCZ = SFalse+ (%:==) SCT SCA = SFalse+ (%:==) SCT SCB = SFalse+ (%:==) SCT SCC = SFalse+ (%:==) SCT SCD = SFalse+ (%:==) SCT SCE = SFalse+ (%:==) SCT SCF = SFalse+ (%:==) SCT SCG = SFalse+ (%:==) SCT SCH = SFalse+ (%:==) SCT SCI = SFalse+ (%:==) SCT SCJ = SFalse+ (%:==) SCT SCK = SFalse+ (%:==) SCT SCL = SFalse+ (%:==) SCT SCM = SFalse+ (%:==) SCT SCN = SFalse+ (%:==) SCT SCO = SFalse+ (%:==) SCT SCP = SFalse+ (%:==) SCT SCQ = SFalse+ (%:==) SCT SCR = SFalse+ (%:==) SCT SCS = SFalse+ (%:==) SCT SCT = STrue+ (%:==) SCT SCU = SFalse+ (%:==) SCT SCV = SFalse+ (%:==) SCT SCW = SFalse+ (%:==) SCT SCX = SFalse+ (%:==) SCT SCY = SFalse+ (%:==) SCT SCZ = SFalse+ (%:==) SCU SCA = SFalse+ (%:==) SCU SCB = SFalse+ (%:==) SCU SCC = SFalse+ (%:==) SCU SCD = SFalse+ (%:==) SCU SCE = SFalse+ (%:==) SCU SCF = SFalse+ (%:==) SCU SCG = SFalse+ (%:==) SCU SCH = SFalse+ (%:==) SCU SCI = SFalse+ (%:==) SCU SCJ = SFalse+ (%:==) SCU SCK = SFalse+ (%:==) SCU SCL = SFalse+ (%:==) SCU SCM = SFalse+ (%:==) SCU SCN = SFalse+ (%:==) SCU SCO = SFalse+ (%:==) SCU SCP = SFalse+ (%:==) SCU SCQ = SFalse+ (%:==) SCU SCR = SFalse+ (%:==) SCU SCS = SFalse+ (%:==) SCU SCT = SFalse+ (%:==) SCU SCU = STrue+ (%:==) SCU SCV = SFalse+ (%:==) SCU SCW = SFalse+ (%:==) SCU SCX = SFalse+ (%:==) SCU SCY = SFalse+ (%:==) SCU SCZ = SFalse+ (%:==) SCV SCA = SFalse+ (%:==) SCV SCB = SFalse+ (%:==) SCV SCC = SFalse+ (%:==) SCV SCD = SFalse+ (%:==) SCV SCE = SFalse+ (%:==) SCV SCF = SFalse+ (%:==) SCV SCG = SFalse+ (%:==) SCV SCH = SFalse+ (%:==) SCV SCI = SFalse+ (%:==) SCV SCJ = SFalse+ (%:==) SCV SCK = SFalse+ (%:==) SCV SCL = SFalse+ (%:==) SCV SCM = SFalse+ (%:==) SCV SCN = SFalse+ (%:==) SCV SCO = SFalse+ (%:==) SCV SCP = SFalse+ (%:==) SCV SCQ = SFalse+ (%:==) SCV SCR = SFalse+ (%:==) SCV SCS = SFalse+ (%:==) SCV SCT = SFalse+ (%:==) SCV SCU = SFalse+ (%:==) SCV SCV = STrue+ (%:==) SCV SCW = SFalse+ (%:==) SCV SCX = SFalse+ (%:==) SCV SCY = SFalse+ (%:==) SCV SCZ = SFalse+ (%:==) SCW SCA = SFalse+ (%:==) SCW SCB = SFalse+ (%:==) SCW SCC = SFalse+ (%:==) SCW SCD = SFalse+ (%:==) SCW SCE = SFalse+ (%:==) SCW SCF = SFalse+ (%:==) SCW SCG = SFalse+ (%:==) SCW SCH = SFalse+ (%:==) SCW SCI = SFalse+ (%:==) SCW SCJ = SFalse+ (%:==) SCW SCK = SFalse+ (%:==) SCW SCL = SFalse+ (%:==) SCW SCM = SFalse+ (%:==) SCW SCN = SFalse+ (%:==) SCW SCO = SFalse+ (%:==) SCW SCP = SFalse+ (%:==) SCW SCQ = SFalse+ (%:==) SCW SCR = SFalse+ (%:==) SCW SCS = SFalse+ (%:==) SCW SCT = SFalse+ (%:==) SCW SCU = SFalse+ (%:==) SCW SCV = SFalse+ (%:==) SCW SCW = STrue+ (%:==) SCW SCX = SFalse+ (%:==) SCW SCY = SFalse+ (%:==) SCW SCZ = SFalse+ (%:==) SCX SCA = SFalse+ (%:==) SCX SCB = SFalse+ (%:==) SCX SCC = SFalse+ (%:==) SCX SCD = SFalse+ (%:==) SCX SCE = SFalse+ (%:==) SCX SCF = SFalse+ (%:==) SCX SCG = SFalse+ (%:==) SCX SCH = SFalse+ (%:==) SCX SCI = SFalse+ (%:==) SCX SCJ = SFalse+ (%:==) SCX SCK = SFalse+ (%:==) SCX SCL = SFalse+ (%:==) SCX SCM = SFalse+ (%:==) SCX SCN = SFalse+ (%:==) SCX SCO = SFalse+ (%:==) SCX SCP = SFalse+ (%:==) SCX SCQ = SFalse+ (%:==) SCX SCR = SFalse+ (%:==) SCX SCS = SFalse+ (%:==) SCX SCT = SFalse+ (%:==) SCX SCU = SFalse+ (%:==) SCX SCV = SFalse+ (%:==) SCX SCW = SFalse+ (%:==) SCX SCX = STrue+ (%:==) SCX SCY = SFalse+ (%:==) SCX SCZ = SFalse+ (%:==) SCY SCA = SFalse+ (%:==) SCY SCB = SFalse+ (%:==) SCY SCC = SFalse+ (%:==) SCY SCD = SFalse+ (%:==) SCY SCE = SFalse+ (%:==) SCY SCF = SFalse+ (%:==) SCY SCG = SFalse+ (%:==) SCY SCH = SFalse+ (%:==) SCY SCI = SFalse+ (%:==) SCY SCJ = SFalse+ (%:==) SCY SCK = SFalse+ (%:==) SCY SCL = SFalse+ (%:==) SCY SCM = SFalse+ (%:==) SCY SCN = SFalse+ (%:==) SCY SCO = SFalse+ (%:==) SCY SCP = SFalse+ (%:==) SCY SCQ = SFalse+ (%:==) SCY SCR = SFalse+ (%:==) SCY SCS = SFalse+ (%:==) SCY SCT = SFalse+ (%:==) SCY SCU = SFalse+ (%:==) SCY SCV = SFalse+ (%:==) SCY SCW = SFalse+ (%:==) SCY SCX = SFalse+ (%:==) SCY SCY = STrue+ (%:==) SCY SCZ = SFalse+ (%:==) SCZ SCA = SFalse+ (%:==) SCZ SCB = SFalse+ (%:==) SCZ SCC = SFalse+ (%:==) SCZ SCD = SFalse+ (%:==) SCZ SCE = SFalse+ (%:==) SCZ SCF = SFalse+ (%:==) SCZ SCG = SFalse+ (%:==) SCZ SCH = SFalse+ (%:==) SCZ SCI = SFalse+ (%:==) SCZ SCJ = SFalse+ (%:==) SCZ SCK = SFalse+ (%:==) SCZ SCL = SFalse+ (%:==) SCZ SCM = SFalse+ (%:==) SCZ SCN = SFalse+ (%:==) SCZ SCO = SFalse+ (%:==) SCZ SCP = SFalse+ (%:==) SCZ SCQ = SFalse+ (%:==) SCZ SCR = SFalse+ (%:==) SCZ SCS = SFalse+ (%:==) SCZ SCT = SFalse+ (%:==) SCZ SCU = SFalse+ (%:==) SCZ SCV = SFalse+ (%:==) SCZ SCW = SFalse+ (%:==) SCZ SCX = SFalse+ (%:==) SCZ SCY = SFalse+ (%:==) SCZ SCZ = STrue+ instance SDecide (KProxy :: KProxy AChar) where+ (%~) SCA SCA = Proved Refl+ (%~) SCA SCB+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCA SCC+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCA SCD+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCA SCE+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCA SCF+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCA SCG+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCA SCH+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCA SCI+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCA SCJ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCA SCK+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCA SCL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCA SCM+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCA SCN+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCA SCO+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCA SCP+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCA SCQ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCA SCR+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCA SCS+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCA SCT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCA SCU+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCA SCV+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCA SCW+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCA SCX+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCA SCY+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCA SCZ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCB SCA+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCB SCB = Proved Refl+ (%~) SCB SCC+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCB SCD+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCB SCE+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCB SCF+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCB SCG+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCB SCH+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCB SCI+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCB SCJ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCB SCK+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCB SCL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCB SCM+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCB SCN+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCB SCO+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCB SCP+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCB SCQ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCB SCR+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCB SCS+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCB SCT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCB SCU+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCB SCV+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCB SCW+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCB SCX+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCB SCY+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCB SCZ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCC SCA+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCC SCB+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCC SCC = Proved Refl+ (%~) SCC SCD+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCC SCE+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCC SCF+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCC SCG+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCC SCH+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCC SCI+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCC SCJ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCC SCK+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCC SCL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCC SCM+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCC SCN+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCC SCO+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCC SCP+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCC SCQ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCC SCR+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCC SCS+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCC SCT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCC SCU+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCC SCV+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCC SCW+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCC SCX+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCC SCY+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCC SCZ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCD SCA+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCD SCB+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCD SCC+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCD SCD = Proved Refl+ (%~) SCD SCE+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCD SCF+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCD SCG+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCD SCH+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCD SCI+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCD SCJ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCD SCK+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCD SCL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCD SCM+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCD SCN+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCD SCO+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCD SCP+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCD SCQ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCD SCR+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCD SCS+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCD SCT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCD SCU+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCD SCV+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCD SCW+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCD SCX+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCD SCY+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCD SCZ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCE SCA+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCE SCB+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCE SCC+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCE SCD+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCE SCE = Proved Refl+ (%~) SCE SCF+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCE SCG+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCE SCH+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCE SCI+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCE SCJ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCE SCK+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCE SCL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCE SCM+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCE SCN+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCE SCO+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCE SCP+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCE SCQ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCE SCR+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCE SCS+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCE SCT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCE SCU+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCE SCV+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCE SCW+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCE SCX+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCE SCY+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCE SCZ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCF SCA+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCF SCB+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCF SCC+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCF SCD+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCF SCE+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCF SCF = Proved Refl+ (%~) SCF SCG+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCF SCH+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCF SCI+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCF SCJ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCF SCK+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCF SCL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCF SCM+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCF SCN+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCF SCO+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCF SCP+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCF SCQ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCF SCR+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCF SCS+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCF SCT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCF SCU+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCF SCV+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCF SCW+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCF SCX+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCF SCY+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCF SCZ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCG SCA+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCG SCB+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCG SCC+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCG SCD+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCG SCE+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCG SCF+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCG SCG = Proved Refl+ (%~) SCG SCH+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCG SCI+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCG SCJ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCG SCK+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCG SCL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCG SCM+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCG SCN+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCG SCO+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCG SCP+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCG SCQ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCG SCR+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCG SCS+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCG SCT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCG SCU+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCG SCV+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCG SCW+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCG SCX+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCG SCY+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCG SCZ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCH SCA+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCH SCB+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCH SCC+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCH SCD+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCH SCE+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCH SCF+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCH SCG+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCH SCH = Proved Refl+ (%~) SCH SCI+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCH SCJ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCH SCK+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCH SCL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCH SCM+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCH SCN+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCH SCO+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCH SCP+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCH SCQ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCH SCR+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCH SCS+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCH SCT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCH SCU+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCH SCV+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCH SCW+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCH SCX+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCH SCY+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCH SCZ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCI SCA+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCI SCB+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCI SCC+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCI SCD+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCI SCE+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCI SCF+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCI SCG+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCI SCH+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCI SCI = Proved Refl+ (%~) SCI SCJ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCI SCK+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCI SCL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCI SCM+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCI SCN+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCI SCO+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCI SCP+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCI SCQ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCI SCR+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCI SCS+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCI SCT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCI SCU+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCI SCV+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCI SCW+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCI SCX+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCI SCY+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCI SCZ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCJ SCA+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCJ SCB+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCJ SCC+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCJ SCD+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCJ SCE+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCJ SCF+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCJ SCG+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCJ SCH+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCJ SCI+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCJ SCJ = Proved Refl+ (%~) SCJ SCK+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCJ SCL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCJ SCM+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCJ SCN+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCJ SCO+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCJ SCP+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCJ SCQ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCJ SCR+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCJ SCS+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCJ SCT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCJ SCU+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCJ SCV+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCJ SCW+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCJ SCX+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCJ SCY+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCJ SCZ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCK SCA+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCK SCB+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCK SCC+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCK SCD+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCK SCE+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCK SCF+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCK SCG+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCK SCH+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCK SCI+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCK SCJ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCK SCK = Proved Refl+ (%~) SCK SCL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCK SCM+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCK SCN+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCK SCO+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCK SCP+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCK SCQ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCK SCR+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCK SCS+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCK SCT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCK SCU+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCK SCV+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCK SCW+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCK SCX+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCK SCY+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCK SCZ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCL SCA+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCL SCB+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCL SCC+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCL SCD+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCL SCE+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCL SCF+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCL SCG+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCL SCH+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCL SCI+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCL SCJ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCL SCK+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCL SCL = Proved Refl+ (%~) SCL SCM+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCL SCN+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCL SCO+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCL SCP+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCL SCQ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCL SCR+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCL SCS+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCL SCT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCL SCU+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCL SCV+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCL SCW+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCL SCX+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCL SCY+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCL SCZ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCM SCA+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCM SCB+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCM SCC+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCM SCD+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCM SCE+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCM SCF+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCM SCG+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCM SCH+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCM SCI+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCM SCJ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCM SCK+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCM SCL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCM SCM = Proved Refl+ (%~) SCM SCN+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCM SCO+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCM SCP+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCM SCQ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCM SCR+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCM SCS+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCM SCT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCM SCU+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCM SCV+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCM SCW+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCM SCX+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCM SCY+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCM SCZ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCN SCA+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCN SCB+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCN SCC+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCN SCD+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCN SCE+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCN SCF+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCN SCG+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCN SCH+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCN SCI+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCN SCJ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCN SCK+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCN SCL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCN SCM+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCN SCN = Proved Refl+ (%~) SCN SCO+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCN SCP+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCN SCQ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCN SCR+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCN SCS+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCN SCT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCN SCU+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCN SCV+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCN SCW+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCN SCX+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCN SCY+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCN SCZ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCO SCA+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCO SCB+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCO SCC+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCO SCD+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCO SCE+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCO SCF+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCO SCG+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCO SCH+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCO SCI+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCO SCJ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCO SCK+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCO SCL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCO SCM+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCO SCN+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCO SCO = Proved Refl+ (%~) SCO SCP+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCO SCQ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCO SCR+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCO SCS+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCO SCT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCO SCU+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCO SCV+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCO SCW+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCO SCX+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCO SCY+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCO SCZ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCP SCA+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCP SCB+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCP SCC+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCP SCD+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCP SCE+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCP SCF+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCP SCG+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCP SCH+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCP SCI+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCP SCJ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCP SCK+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCP SCL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCP SCM+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCP SCN+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCP SCO+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCP SCP = Proved Refl+ (%~) SCP SCQ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCP SCR+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCP SCS+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCP SCT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCP SCU+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCP SCV+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCP SCW+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCP SCX+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCP SCY+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCP SCZ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCQ SCA+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCQ SCB+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCQ SCC+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCQ SCD+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCQ SCE+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCQ SCF+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCQ SCG+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCQ SCH+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCQ SCI+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCQ SCJ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCQ SCK+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCQ SCL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCQ SCM+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCQ SCN+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCQ SCO+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCQ SCP+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCQ SCQ = Proved Refl+ (%~) SCQ SCR+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCQ SCS+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCQ SCT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCQ SCU+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCQ SCV+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCQ SCW+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCQ SCX+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCQ SCY+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCQ SCZ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCR SCA+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCR SCB+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCR SCC+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCR SCD+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCR SCE+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCR SCF+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCR SCG+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCR SCH+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCR SCI+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCR SCJ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCR SCK+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCR SCL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCR SCM+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCR SCN+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCR SCO+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCR SCP+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCR SCQ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCR SCR = Proved Refl+ (%~) SCR SCS+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCR SCT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCR SCU+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCR SCV+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCR SCW+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCR SCX+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCR SCY+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCR SCZ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCS SCA+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCS SCB+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCS SCC+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCS SCD+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCS SCE+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCS SCF+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCS SCG+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCS SCH+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCS SCI+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCS SCJ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCS SCK+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCS SCL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCS SCM+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCS SCN+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCS SCO+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCS SCP+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCS SCQ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCS SCR+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCS SCS = Proved Refl+ (%~) SCS SCT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCS SCU+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCS SCV+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCS SCW+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCS SCX+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCS SCY+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCS SCZ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCT SCA+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCT SCB+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCT SCC+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCT SCD+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCT SCE+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCT SCF+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCT SCG+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCT SCH+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCT SCI+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCT SCJ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCT SCK+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCT SCL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCT SCM+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCT SCN+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCT SCO+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCT SCP+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCT SCQ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCT SCR+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCT SCS+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCT SCT = Proved Refl+ (%~) SCT SCU+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCT SCV+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCT SCW+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCT SCX+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCT SCY+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCT SCZ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCU SCA+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCU SCB+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCU SCC+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCU SCD+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCU SCE+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCU SCF+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCU SCG+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCU SCH+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCU SCI+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCU SCJ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCU SCK+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCU SCL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCU SCM+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCU SCN+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCU SCO+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCU SCP+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCU SCQ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCU SCR+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCU SCS+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCU SCT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCU SCU = Proved Refl+ (%~) SCU SCV+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCU SCW+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCU SCX+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCU SCY+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCU SCZ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCV SCA+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCV SCB+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCV SCC+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCV SCD+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCV SCE+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCV SCF+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCV SCG+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCV SCH+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCV SCI+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCV SCJ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCV SCK+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCV SCL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCV SCM+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCV SCN+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCV SCO+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCV SCP+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCV SCQ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCV SCR+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCV SCS+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCV SCT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCV SCU+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCV SCV = Proved Refl+ (%~) SCV SCW+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCV SCX+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCV SCY+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCV SCZ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCW SCA+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCW SCB+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCW SCC+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCW SCD+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCW SCE+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCW SCF+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCW SCG+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCW SCH+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCW SCI+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCW SCJ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCW SCK+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCW SCL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCW SCM+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCW SCN+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCW SCO+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCW SCP+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCW SCQ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCW SCR+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCW SCS+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCW SCT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCW SCU+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCW SCV+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCW SCW = Proved Refl+ (%~) SCW SCX+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCW SCY+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCW SCZ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCX SCA+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCX SCB+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCX SCC+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCX SCD+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCX SCE+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCX SCF+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCX SCG+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCX SCH+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCX SCI+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCX SCJ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCX SCK+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCX SCL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCX SCM+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCX SCN+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCX SCO+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCX SCP+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCX SCQ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCX SCR+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCX SCS+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCX SCT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCX SCU+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCX SCV+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCX SCW+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCX SCX = Proved Refl+ (%~) SCX SCY+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCX SCZ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCY SCA+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCY SCB+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCY SCC+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCY SCD+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCY SCE+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCY SCF+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCY SCG+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCY SCH+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCY SCI+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCY SCJ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCY SCK+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCY SCL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCY SCM+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCY SCN+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCY SCO+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCY SCP+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCY SCQ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCY SCR+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCY SCS+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCY SCT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCY SCU+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCY SCV+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCY SCW+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCY SCX+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCY SCY = Proved Refl+ (%~) SCY SCZ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCZ SCA+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCZ SCB+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCZ SCC+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCZ SCD+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCZ SCE+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCZ SCF+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCZ SCG+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCZ SCH+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCZ SCI+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCZ SCJ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCZ SCK+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCZ SCL+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCZ SCM+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCZ SCN+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCZ SCO+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCZ SCP+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCZ SCQ+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCZ SCR+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCZ SCS+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCZ SCT+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCZ SCU+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCZ SCV+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCZ SCW+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCZ SCX+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCZ SCY+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SCZ SCZ = Proved Refl+ instance SingI CA where+ sing = SCA+ instance SingI CB where+ sing = SCB+ instance SingI CC where+ sing = SCC+ instance SingI CD where+ sing = SCD+ instance SingI CE where+ sing = SCE+ instance SingI CF where+ sing = SCF+ instance SingI CG where+ sing = SCG+ instance SingI CH where+ sing = SCH+ instance SingI CI where+ sing = SCI+ instance SingI CJ where+ sing = SCJ+ instance SingI CK where+ sing = SCK+ instance SingI CL where+ sing = SCL+ instance SingI CM where+ sing = SCM+ instance SingI CN where+ sing = SCN+ instance SingI CO where+ sing = SCO+ instance SingI CP where+ sing = SCP+ instance SingI CQ where+ sing = SCQ+ instance SingI CR where+ sing = SCR+ instance SingI CS where+ sing = SCS+ instance SingI CT where+ sing = SCT+ instance SingI CU where+ sing = SCU+ instance SingI CV where+ sing = SCV+ instance SingI CW where+ sing = SCW+ instance SingI CX where+ sing = SCX+ instance SingI CY where+ sing = SCY+ instance SingI CZ where+ sing = SCZ+ data instance Sing (z :: Attribute)+ = forall (n :: [AChar]) (n :: U). z ~ Attr n n =>+ SAttr (Sing n) (Sing n)+ type SAttribute (z :: Attribute) = Sing z+ instance SingKind (KProxy :: KProxy Attribute) where+ type DemoteRep (KProxy :: KProxy Attribute) = Attribute+ fromSing (SAttr b b) = Attr (fromSing b) (fromSing b)+ toSing (Attr b b)+ = case+ (toSing b :: SomeSing (KProxy :: KProxy [AChar]), + toSing b :: SomeSing (KProxy :: KProxy U))+ of {+ (SomeSing c, SomeSing c) -> SomeSing (SAttr c c) }+ instance (SingI n, SingI n) =>+ SingI (Attr (n :: [AChar]) (n :: U)) where+ sing = SAttr sing sing+ data instance Sing (z :: Schema)+ = forall (n :: [Attribute]). z ~ Sch n => SSch (Sing n)+ type SSchema (z :: Schema) = Sing z+ instance SingKind (KProxy :: KProxy Schema) where+ type DemoteRep (KProxy :: KProxy Schema) = Schema+ fromSing (SSch b) = Sch (fromSing b)+ toSing (Sch b)+ = case toSing b :: SomeSing (KProxy :: KProxy [Attribute]) of {+ SomeSing c -> SomeSing (SSch c) }+ instance SingI n => SingI (Sch (n :: [Attribute])) where+ sing = SSch sing+ sAppend ::+ forall (t :: Schema) (t :: Schema).+ Sing t -> Sing t -> Sing (Append t t)+ sAppend (SSch s1) (SSch s2) = SSch ((%:++) s1 s2)+ sAttrNotIn ::+ forall (t :: Attribute) (t :: Schema).+ Sing t -> Sing t -> Sing (AttrNotIn t t)+ sAttrNotIn _ (SSch SNil) = STrue+ sAttrNotIn (SAttr name u) (SSch (SCons (SAttr name' _) t))+ = (%:&&) ((%:/=) name name') (sAttrNotIn (SAttr name u) (SSch t))+ sDisjoint ::+ forall (t :: Schema) (t :: Schema).+ Sing t -> Sing t -> Sing (Disjoint t t)+ sDisjoint (SSch SNil) _ = STrue+ sDisjoint (SSch (SCons h t)) s+ = (%:&&) (sAttrNotIn h s) (sDisjoint (SSch t) s)+ sOccurs ::+ forall (t :: [AChar]) (t :: Schema).+ Sing t -> Sing t -> Sing (Occurs t t)+ sOccurs _ (SSch SNil) = SFalse+ sOccurs name (SSch (SCons (SAttr name' _) attrs))+ = (%:||) ((%:==) name name') (sOccurs name (SSch attrs))+ sLookup ::+ forall (t :: [AChar]) (t :: Schema).+ Sing t -> Sing t -> Sing (Lookup t t)+ sLookup _ (SSch SNil) = undefined+ sLookup name (SSch (SCons (SAttr name' u) attrs))+ = sIf ((%:==) name name') u (sLookup name (SSch attrs))+GradingClient/Database.hs:0:0: Splicing declarations+ return [] ======> GradingClient/Database.hs:0:0:+GradingClient/Database.hs:(0,0)-(0,0): Splicing expression+ cases ''Row [| r |] [| changeId (n ++ (getId r)) r |]+ ======>+ case r of {+ EmptyRow _ -> changeId (n ++ (getId r)) r+ ConsRow _ _ -> changeId (n ++ (getId r)) r }
+ tests/compile-and-dump/GradingClient/Database.hs view
@@ -0,0 +1,536 @@+{- Database.hs++(c) Richard Eisenberg 2012+eir@cis.upenn.edu++This file contains the full code for the database interface example+presented in /Dependently typed programming with singletons/++-}++{-# LANGUAGE PolyKinds, DataKinds, TemplateHaskell, TypeFamilies,+ GADTs, TypeOperators, RankNTypes, FlexibleContexts, UndecidableInstances,+ FlexibleInstances, ScopedTypeVariables, MultiParamTypeClasses,+ OverlappingInstances, ConstraintKinds, CPP #-}++-- The OverlappingInstances is needed only to allow the InC and SubsetC classes.+-- This is simply a convenience so that GHC can infer the necessary proofs of+-- schema inclusion. The library could easily be designed without this flag,+-- but it would require a client to explicity build proof terms from+-- InProof and Subset.++module GradingClient.Database where++import Prelude hiding ( tail, id )+import Data.Singletons.TH+import Data.Singletons.Prelude+import Control.Monad+import Data.List hiding ( tail )+import Control.Monad.Error++$(singletons [d|+ -- Basic Nat type+ data Nat = Zero | Succ Nat deriving (Eq, Ord)+ |])++-- Conversions to any from Integers+fromNat :: Nat -> Integer+fromNat Zero = 0+fromNat (Succ n) = (fromNat n) + 1++toNat :: Integer -> Nat+toNat 0 = Zero+toNat n | n > 0 = Succ (toNat (n - 1))+toNat _ = error "Converting negative to Nat"++-- Display and read Nats using decimal digits+instance Show Nat where+ show = show . fromNat+instance Read Nat where+ readsPrec n s = map (\(a,rest) -> (toNat a,rest)) $ readsPrec n s++$(singletons [d|+ -- Our "U"niverse of types. These types can be stored in our database.+ data U = BOOL+ | STRING+ | NAT+ | VEC U Nat deriving (Read, Eq, Show)++ -- A re-definition of Char as an algebraic data type.+ -- This is necessary to allow for promotion and type-level Strings.+ data AChar = CA | CB | CC | CD | CE | CF | CG | CH | CI+ | CJ | CK | CL | CM | CN | CO | CP | CQ | CR+ | CS | CT | CU | CV | CW | CX | CY | CZ+ deriving (Read, Show, Eq)++ -- A named attribute in our database+ data Attribute = Attr [AChar] U++ -- A schema is an ordered list of named attributes+ data Schema = Sch [Attribute]++ -- append two schemas+ append :: Schema -> Schema -> Schema+ append (Sch s1) (Sch s2) = Sch (s1 ++ s2)++ -- predicate to check that a schema is free of a certain attribute+ attrNotIn :: Attribute -> Schema -> Bool+ attrNotIn _ (Sch []) = True+ attrNotIn (Attr name u) (Sch ((Attr name' _) : t)) =+ (name /= name') && (attrNotIn (Attr name u) (Sch t))++ -- predicate to check that two schemas are disjoint+ disjoint :: Schema -> Schema -> Bool+ disjoint (Sch []) _ = True+ disjoint (Sch (h : t)) s = (attrNotIn h s) && (disjoint (Sch t) s)++ -- predicate to check if a name occurs in a schema+ occurs :: [AChar] -> Schema -> Bool+ occurs _ (Sch []) = False+ occurs name (Sch ((Attr name' _) : attrs)) =+ name == name' || occurs name (Sch attrs)++ -- looks up an element type from a schema+ lookup :: [AChar] -> Schema -> U+ lookup _ (Sch []) = undefined+ lookup name (Sch ((Attr name' u) : attrs)) =+ if name == name' then u else lookup name (Sch attrs)+ |])++-- The El type family gives us the type associated with a constructor+-- of U:+type family El (u :: U) :: *+type instance El BOOL = Bool+type instance El STRING = String+type instance El NAT = Nat+type instance El (VEC u n) = Vec (El u) n++-- Length-indexed vectors+data Vec :: * -> Nat -> * where+ VNil :: Vec a Zero+ VCons :: a -> Vec a n -> Vec a (Succ n)++-- Read instances are keyed by the index of the vector to aid in parsing+instance Read (Vec a Zero) where+ readsPrec _ s = [(VNil, s)]+instance (Read a, Read (Vec a n)) => Read (Vec a (Succ n)) where+ readsPrec n s = do+ (a, rest) <- readsPrec n s+ (tail, restrest) <- readsPrec n rest+ return (VCons a tail, restrest)++-- Because the Read instances are keyed by the length of the vector,+-- it is not obvious to the compiler that all Vecs have a Read instance.+-- We must make a short inductive proof of this fact.++-- First, we define a datatype to store the resulting instance, keyed+-- by the parameters to Vec:+data VecReadInstance a n where+ VecReadInstance :: Read (Vec a n) => VecReadInstance a n++-- Then, we make a function that produces an instance of Read for a+-- Vec, given the datatype it is over and its length, both encoded+-- using singleton types:+vecReadInstance :: Read (El u) => SU u -> SNat n -> VecReadInstance (El u) n+vecReadInstance _ SZero = VecReadInstance+vecReadInstance u (SSucc n) = case vecReadInstance u n of+ VecReadInstance -> VecReadInstance++-- The Show instance can be straightforwardly defined:+instance Show a => Show (Vec a n) where+ show VNil = ""+ show (VCons h t) = (show h) ++ " " ++ (show t)++-- We need to be able to Read and Show elements of our database, so+-- we must know that any type of the form (El u) for some (u :: U)+-- has a Read and Show instance. Because we can't declare this instance+-- directly (as, in general, declaring an instance of a type family+-- would be unsound), we provide inductive proofs that these instances+-- exist:+data ElUReadInstance u where+ ElUReadInstance :: Read (El u) => ElUReadInstance u++elUReadInstance :: Sing u -> ElUReadInstance u+elUReadInstance SBOOL = ElUReadInstance+elUReadInstance SSTRING = ElUReadInstance+elUReadInstance SNAT = ElUReadInstance+elUReadInstance (SVEC u n) = case elUReadInstance u of+ ElUReadInstance -> case vecReadInstance u n of+ VecReadInstance -> ElUReadInstance++data ElUShowInstance u where+ ElUShowInstance :: Show (El u) => ElUShowInstance u++elUShowInstance :: Sing u -> ElUShowInstance u+elUShowInstance SBOOL = ElUShowInstance+elUShowInstance SSTRING = ElUShowInstance+elUShowInstance SNAT = ElUShowInstance+elUShowInstance (SVEC u _) = case elUShowInstance u of+ ElUShowInstance -> ElUShowInstance++showAttrProof :: Sing (Attr nm u) -> ElUShowInstance u+showAttrProof (SAttr _ u) = elUShowInstance u++-- A Row is one row of our database table, keyed by its schema.+data Row :: Schema -> * where+ EmptyRow :: [Int] -> Row (Sch '[]) -- the Ints are the unique id of the row+ ConsRow :: El u -> Row (Sch s) -> Row (Sch ((Attr name u) ': s))++-- We build Show instances for a Row element by element:+instance Show (Row (Sch '[])) where+ show (EmptyRow n) = "(id=" ++ (show n) ++ ")"+instance (Show (El u), Show (Row (Sch attrs))) =>+ Show (Row (Sch ((Attr name u) ': attrs))) where+ show (ConsRow h t) = case t of+ EmptyRow n -> (show h) ++ " (id=" ++ (show n) ++ ")"+ _ -> (show h) ++ ", " ++ (show t)++-- A Handle in our system is an abstract handle to a loaded table.+-- The constructor is not exported. In our simplistic case, we+-- just store the list of rows. A more sophisticated implementation+-- could store some identifier to the connection to an external database.+data Handle :: Schema -> * where+ Handle :: [Row s] -> Handle s++-- The following functions parse our very simple flat file database format.++-- The file, with a name ending in ".dat", consists of a sequence of lines,+-- where each line contains one entry in the table. There is no row separator;+-- if a row contains n pieces of data, that row is represented in n lines in+-- the file.++-- A schema is stored in a file of the same name, except ending in ".schema".+-- Each line in the file is a constructor of U indicating the type of the+-- corresponding row element.++-- Use Either for error handling in parsing functions+type ErrorM = Either String++-- This function is relatively uninteresting except for its use of+-- pattern matching to introduce the instances of Read and Show for+-- elements+readRow :: Int -> SSchema s -> [String] -> ErrorM (Row s, [String])+readRow id (SSch SNil) strs =+ return (EmptyRow [id], strs)+readRow _ (SSch (SCons _ _)) [] =+ throwError "Ran out of data while processing row"+readRow id (SSch (SCons (SAttr _ u) at)) (sh:st) = do+ (rowTail, strTail) <- readRow id (SSch at) st+ case elUReadInstance u of+ ElUReadInstance ->+ let results = readsPrec 0 sh in+ if null results+ then throwError $ "No parse of " ++ sh ++ " as a " +++ (show (fromSing u))+ else+ let item = fst $ head results in+ case elUShowInstance u of+ ElUShowInstance -> return (ConsRow item rowTail, strTail)++readRows :: SSchema s -> [String] -> [Row s] -> ErrorM [Row s]+readRows _ [] soFar = return soFar+readRows sch lst soFar = do+ (row, rest) <- readRow (length soFar) sch lst+ readRows sch rest (row : soFar)++-- Given the name of a database and its schema, return a handle to the+-- database.+connect :: String -> SSchema s -> IO (Handle s)+connect name schema = do+ schString <- readFile (name ++ ".schema")+ let schEntries = lines schString+ usFound = map read schEntries -- load schema just using "read"+ (Sch attrs) = fromSing schema+ usExpected = map (\(Attr _ u) -> u) attrs+ unless (usFound == usExpected) -- compare found schema with expected+ (fail "Expected schema does not match found schema")+ dataString <- readFile (name ++ ".dat")+ let dataEntries = lines dataString+ result = readRows schema dataEntries [] -- read actual data+ case result of+ Left errorMsg -> fail errorMsg+ Right rows -> return $ Handle rows++-- In order to define strongly-typed projection from a row, we need to have a notion+-- that one schema is a subset of another. We permit the schemas to have their columns+-- in different orders. We define this subset relation via two inductively defined+-- propositions. In Haskell, these inductively defined propositions take the form of+-- GADTs. In their original form, they would look like this:+{-+data InProof :: Attribute -> Schema -> * where+ InElt :: InProof attr (Sch (attr ': schTail))+ InTail :: InProof attr (Sch attrs) -> InProof attr (Sch (a ': attrs))++data SubsetProof :: Schema -> Schema -> * where+ SubsetEmpty :: SubsetProof (Sch '[]) s'+ SubsetCons :: InProof attr s' -> SubsetProof (Sch attrs) s' ->+ SubsetProof (Sch (attr ': attrs)) s'+-}+-- However, it would be convenient to users of the database library not to require+-- building these proofs manually. So, we define type classes so that the compiler+-- builds the proofs automatically. To make everything work well together, we also+-- make the parameters to the proof GADT constructors implicit -- i.e. in the form+-- of type class constraints.++data InProof :: Attribute -> Schema -> * where+ InElt :: InProof attr (Sch (attr ': schTail))+ InTail :: InC name u (Sch attrs) => InProof (Attr name u) (Sch (a ': attrs))++class InC (name :: [AChar]) (u :: U) (sch :: Schema) where+ inProof :: InProof (Attr name u) sch+instance InC name u (Sch ((Attr name u) ': schTail)) where+ inProof = InElt+instance InC name u (Sch attrs) => InC name u (Sch (a ': attrs)) where+ inProof = InTail++data SubsetProof :: Schema -> Schema -> * where+ SubsetEmpty :: SubsetProof (Sch '[]) s'+ SubsetCons :: (InC name u s', SubsetC (Sch attrs) s') =>+ SubsetProof (Sch ((Attr name u) ': attrs)) s'++class SubsetC (s :: Schema) (s' :: Schema) where+ subset :: SubsetProof s s'++instance SubsetC (Sch '[]) s' where+ subset = SubsetEmpty+instance (InC name u s', SubsetC (Sch attrs) s') =>+ SubsetC (Sch ((Attr name u) ': attrs)) s' where+ subset = SubsetCons++-- To access the data in a structured (and well-typed!) way, we use+-- an RA (short for Relational Algebra). An RA is indexed by the schema+-- of the data it produces.+data RA :: Schema -> * where+ -- The RA includes all data represented by the handle.+ Read :: Handle s -> RA s++ -- The RA is a union of the rows represented by the two RAs provided.+ -- Note that the schemas of the two RAs must be the same for this+ -- constructor use to type-check.+ Union :: RA s -> RA s -> RA s++ -- The RA is the list of rows in the first RA, omitting those in the+ -- second. Once again, the schemas must match.+ Diff :: RA s -> RA s -> RA s++ -- The RA is a Cartesian product of the two RAs provided. Note that+ -- the schemas of the two provided RAs must be disjoint.+ Product :: (Disjoint s s' ~ True, SingI s, SingI s') =>+ RA s -> RA s' -> RA (Append s s')++ -- The RA is a projection conforming to the schema provided. The+ -- type-checker ensures that this schema is a subset of the data+ -- included in the provided RA.+ Project :: (SubsetC s' s, SingI s) =>+ SSchema s' -> RA s -> RA s'++ -- The RA contains only those rows of the provided RA for which+ -- the provided expression evaluates to True. Note that the+ -- schema of the provided RA and the resultant RA are the same+ -- because the columns of data are the same. Also note that+ -- the expression must return a Bool for this to type-check.+ Select :: Expr s BOOL -> RA s -> RA s++-- Other constructors would be added in a more robust database+-- implementation.++-- An Expr is used with the Select constructor to choose some+-- subset of rows from a table. Expressions are indexed by the+-- schema over which they operate and the return value they+-- produce.+data Expr :: Schema -> U -> * where+ -- Equality among two elements+ Equal :: Eq (El u) => Expr s u -> Expr s u -> Expr s BOOL++ -- A less-than comparison among two Nats+ LessThan :: Expr s NAT -> Expr s NAT -> Expr s BOOL++ -- A literal number+ LiteralNat :: Integer -> Expr s NAT++ -- Projection in an expression -- evaluates to the value+ -- of the named attribute.+ Element :: (Occurs nm s ~ True) =>+ SSchema s -> Sing nm -> Expr s (Lookup nm s)++ -- A more robust implementation would include more constructors++-- Retrieves the id from a row. Ids are used when computing unions and+-- differences.+getId :: Row s -> [Int]+getId (EmptyRow n) = n+getId (ConsRow _ t) = getId t++-- Changes the id of a row to a new value+changeId :: [Int] -> Row s -> Row s+changeId n (EmptyRow _) = EmptyRow n+changeId n (ConsRow h t) = ConsRow h (changeId n t)++-- Equality for rows based on ids.+eqRow :: Row s -> Row s -> Bool+eqRow r1 r2 = getId r1 == getId r2++-- Equality for attributes based on names+eqAttr :: Attribute -> Attribute -> Bool+eqAttr (Attr nm _) (Attr nm' _) = nm == nm'++-- Appends two rows. There are three suspicious case statements -- they are+-- suspicious in that the different branches are all exactly identical. Here+-- is why they are needed:++-- The two case statements on r are necessary to deconstruct the index in the+-- type of r; GHC does not use the fact that s' must be (Sch a') for some a'.+-- By doing a case analysis on r, GHC uses the types given in the different+-- constructors for Row, both of which give the form of s' as (Sch a'). This+-- deconstruction is necessary for the type family Append to compute, because+-- Append is defined only when its second argument is of the form (Sch a').++-- The case statement on rowAppend t r is necessary to avoid potential+-- overlapping instances for the SingRep class; the instances are needed for+-- the call to ConsRow. The potential for overlapping instances comes from+-- ambiguity in the component types of (Append s s'). By doing case analysis+-- on rowAppend t r, these variables become fixed, and the potential for+-- overlapping instances disappears.++-- We use the "cases" Singletons library operation to produce the case+-- analysis in the first clause. This "cases" operation produces a case+-- statement where each branch is identical and each constructor parameter+-- is ignored. The "cases" operation does not work for the second clause+-- because the code in the clause depends on definitions generated earlier.+-- Template Haskell restricts certain dependencies between auto-generated+-- code blocks to prevent the possibility of circular dependencies.+-- In this case, if the $(singletons ...) blocks above were in a different+-- module, the "cases" operation would be applicable here.++$( return [] )++rowAppend :: Row s -> Row s' -> Row (Append s s')+rowAppend (EmptyRow n) r = $(cases ''Row [| r |]+ [| changeId (n ++ (getId r)) r |])+rowAppend (ConsRow h t) r = case r of+ EmptyRow _ ->+ case rowAppend t r of+ EmptyRow _ -> ConsRow h (rowAppend t r)+ ConsRow _ _ -> ConsRow h (rowAppend t r)+ ConsRow _ _ ->+ case rowAppend t r of+ EmptyRow _ -> ConsRow h (rowAppend t r)+ ConsRow _ _ -> ConsRow h (rowAppend t r)++-- Choose the elements of one list based on truth values in another+choose :: [Bool] -> [a] -> [a]+choose [] _ = []+choose (False : btail) (_ : t) = choose btail t+choose (True : btail) (h : t) = h : (choose btail t)+choose _ [] = []++-- The query function is the eliminator for an RA. It returns a list of+-- rows containing the data produced by the RA.+query :: forall s. SingI s => RA s -> IO [Row s]+query (Read (Handle rows)) = return rows+query (Union ra rb) = do+ rowsa <- query ra+ rowsb <- query rb+ return $ unionBy eqRow rowsa rowsb+query (Diff ra rb) = do+ rowsa <- query ra+ rowsb <- query rb+ return $ deleteFirstsBy eqRow rowsa rowsb+query (Product ra rb) = do+ rowsa <- query ra+ rowsb <- query rb+ return $ do -- entering the [] Monad+ rowa <- rowsa+ rowb <- rowsb+ return $ rowAppend rowa rowb+query (Project sch ra) = do+ rows <- query ra+ return $ map (projectRow sch) rows+ where -- The projectRow function uses the relationship encoded in the Subset+ -- relation to project the requested columns of data in a type-safe manner.++ -- It recurs on the structure of the provided schema, creating the output+ -- row to be in the same order as the input schema. This is necessary for+ -- the output to type-check, as it is indexed by the input schema.++ -- We use explicit quantification to get access to scoped type variables.+ projectRow :: forall (sch :: Schema) (s' :: Schema).+ SubsetC sch s' => SSchema sch -> Row s' -> Row sch++ -- Base case: empty schema+ projectRow (SSch SNil) r = EmptyRow (getId r)++ -- In the recursive case, we need to pattern-match on the proof that+ -- the provided schema is a subset of the provided RA. We extract this+ -- proof (of type SubsetProof s s') from the SubsetC instance using the+ -- subset method.+ projectRow (SSch (SCons attr tail)) r =+ case subset :: SubsetProof sch s' of++ -- Because we know that the schema is non-empty, the only possibility+ -- here is SubsetCons:+ SubsetCons ->+ let rtail = projectRow (SSch tail) r in+ case attr of+ SAttr _ u -> case elUShowInstance u of+ ElUShowInstance -> ConsRow (extractElt attr r) rtail++ -- GHC correctly determines that this case is impossible if it is+ -- not commented.+ -- SubsetEmpty -> undefined <== IMPOSSIBLE++ -- However, the current version of GHC (7.5) does not suppress warnings+ -- for incomplete pattern matches when the remaining cases are impossible.+ -- So, we include this case (impossible to reach for any terminated value)+ -- to suppress the warning.+ _ -> error "Type checking failed"++ -- Retrieves the element, looked up by the name of the provided attribute,+ -- from a row. The explicit quantification is necessary to create the scoped+ -- type variables to use in the return type of <<inProof>>+ extractElt :: forall nm u sch. InC nm u sch =>+ Sing (Attr nm u) -> Row sch -> El u+ extractElt attr r = case inProof :: InProof (Attr nm u) sch of+ InElt -> case r of+ ConsRow h _ -> h+ -- EmptyRow _ -> undefined <== IMPOSSIBLE+ _ -> error "Type checking failed"+ InTail -> case r of+ ConsRow _ t -> extractElt attr t+ -- EmptyRow _ -> undefined <== IMPOSSBLE+ _ -> error "Type checking failed"++query (Select expr r) = do+ rows <- query r+ let vals = map (eval expr) rows+ return $ choose vals rows+ where -- Evaluates an expression+ eval :: forall s' u. SingI s' => Expr s' u -> Row s' -> El u+ eval (Element _ (name :: Sing name)) row =+ case row of+ -- EmptyRow _ -> undefined <== IMPOSSIBLE+ ConsRow h t -> case row of+ (ConsRow _ _ :: Row (Sch ((Attr name' u') ': attrs))) ->+ case sing :: Sing s' of+ -- SSch SNil -> undefined <== IMPOSSIBLE+ SSch (SCons (SAttr name' _) stail) ->+ case name %:== name' of+ STrue -> h+ SFalse -> withSingI stail (eval (Element (SSch stail) name) t)+ _ -> bugInGHC+ _ -> bugInGHC++ eval (Equal (e1 :: Expr s' u') e2) row =+ let v1 = eval e1 row+ v2 = eval e2 row in+ v1 == v2++ -- Note that the types really help us here: the LessThan constructor is+ -- defined only over Expr s NAT, so we know that evaluating e1 and e2 will+ -- yield Nats, which are a member of the Ord type class.+ eval (LessThan e1 e2) row =+ let v1 = eval e1 row+ v2 = eval e2 row in+ v1 < v2++ eval (LiteralNat x) _ = toNat x
+ tests/compile-and-dump/GradingClient/Main.ghc76.template view
@@ -0,0 +1,75 @@+GradingClient/Main.hs:0:0: Splicing declarations+ singletons+ [d| lastName, majorName, gradeName, yearName, firstName :: [AChar]+ lastName = [CL, CA, CS, CT]+ firstName = [CF, CI, CR, CS, CT]+ yearName = [CY, CE, CA, CR]+ gradeName = [CG, CR, CA, CD, CE]+ majorName = [CM, CA, CJ, CO, CR]+ gradingSchema :: Schema+ gradingSchema+ = Sch+ [Attr lastName STRING, Attr firstName STRING, Attr yearName NAT,+ Attr gradeName NAT, Attr majorName BOOL]+ names :: Schema+ names = Sch [Attr firstName STRING, Attr lastName STRING] |]+ ======>+ GradingClient/Main.hs:(0,0)-(0,0)+ lastName :: [AChar]+ majorName :: [AChar]+ gradeName :: [AChar]+ yearName :: [AChar]+ firstName :: [AChar]+ lastName = [CL, CA, CS, CT]+ firstName = [CF, CI, CR, CS, CT]+ yearName = [CY, CE, CA, CR]+ gradeName = [CG, CR, CA, CD, CE]+ majorName = [CM, CA, CJ, CO, CR]+ gradingSchema :: Schema+ gradingSchema+ = Sch+ [Attr lastName STRING, Attr firstName STRING, Attr yearName NAT,+ Attr gradeName NAT, Attr majorName BOOL]+ names :: Schema+ names = Sch [Attr firstName STRING, Attr lastName STRING]+ type LastName = '[CL, CA, CS, CT]+ type FirstName = '[CF, CI, CR, CS, CT]+ type YearName = '[CY, CE, CA, CR]+ type GradeName = '[CG, CR, CA, CD, CE]+ type MajorName = '[CM, CA, CJ, CO, CR]+ type GradingSchema =+ Sch '[Attr LastName STRING,+ Attr FirstName STRING,+ Attr YearName NAT,+ Attr GradeName NAT,+ Attr MajorName BOOL]+ type Names = Sch '[Attr FirstName STRING, Attr LastName STRING]+ sLastName :: Sing LastName+ sMajorName :: Sing MajorName+ sGradeName :: Sing GradeName+ sYearName :: Sing YearName+ sFirstName :: Sing FirstName+ sLastName = SCons SCL (SCons SCA (SCons SCS (SCons SCT SNil)))+ sFirstName+ = SCons SCF (SCons SCI (SCons SCR (SCons SCS (SCons SCT SNil))))+ sYearName = SCons SCY (SCons SCE (SCons SCA (SCons SCR SNil)))+ sGradeName+ = SCons SCG (SCons SCR (SCons SCA (SCons SCD (SCons SCE SNil))))+ sMajorName+ = SCons SCM (SCons SCA (SCons SCJ (SCons SCO (SCons SCR SNil))))+ sGradingSchema :: Sing GradingSchema+ sGradingSchema+ = SSch+ (SCons+ (SAttr sLastName SSTRING)+ (SCons+ (SAttr sFirstName SSTRING)+ (SCons+ (SAttr sYearName SNAT)+ (SCons+ (SAttr sGradeName SNAT) (SCons (SAttr sMajorName SBOOL) SNil)))))+ sNames :: Sing Names+ sNames+ = SSch+ (SCons+ (SAttr sFirstName SSTRING) (SCons (SAttr sLastName SSTRING) SNil))
+ tests/compile-and-dump/GradingClient/Main.ghc78.template view
@@ -0,0 +1,75 @@+GradingClient/Main.hs:0:0: Splicing declarations+ singletons+ [d| lastName, majorName, gradeName, yearName, firstName :: [AChar]+ lastName = [CL, CA, CS, CT]+ firstName = [CF, CI, CR, CS, CT]+ yearName = [CY, CE, CA, CR]+ gradeName = [CG, CR, CA, CD, CE]+ majorName = [CM, CA, CJ, CO, CR]+ gradingSchema :: Schema+ gradingSchema+ = Sch+ [Attr lastName STRING, Attr firstName STRING, Attr yearName NAT,+ Attr gradeName NAT, Attr majorName BOOL]+ names :: Schema+ names = Sch [Attr firstName STRING, Attr lastName STRING] |]+ ======>+ GradingClient/Main.hs:(0,0)-(0,0)+ lastName :: [AChar]+ majorName :: [AChar]+ gradeName :: [AChar]+ yearName :: [AChar]+ firstName :: [AChar]+ lastName = [CL, CA, CS, CT]+ firstName = [CF, CI, CR, CS, CT]+ yearName = [CY, CE, CA, CR]+ gradeName = [CG, CR, CA, CD, CE]+ majorName = [CM, CA, CJ, CO, CR]+ gradingSchema :: Schema+ gradingSchema+ = Sch+ [Attr lastName STRING, Attr firstName STRING, Attr yearName NAT,+ Attr gradeName NAT, Attr majorName BOOL]+ names :: Schema+ names = Sch [Attr firstName STRING, Attr lastName STRING]+ type LastName = '[CL, CA, CS, CT]+ type FirstName = '[CF, CI, CR, CS, CT]+ type YearName = '[CY, CE, CA, CR]+ type GradeName = '[CG, CR, CA, CD, CE]+ type MajorName = '[CM, CA, CJ, CO, CR]+ type GradingSchema =+ Sch '[Attr LastName STRING,+ Attr FirstName STRING,+ Attr YearName NAT,+ Attr GradeName NAT,+ Attr MajorName BOOL]+ type Names = Sch '[Attr FirstName STRING, Attr LastName STRING]+ sLastName :: Sing LastName+ sMajorName :: Sing MajorName+ sGradeName :: Sing GradeName+ sYearName :: Sing YearName+ sFirstName :: Sing FirstName+ sLastName = SCons SCL (SCons SCA (SCons SCS (SCons SCT SNil)))+ sFirstName+ = SCons SCF (SCons SCI (SCons SCR (SCons SCS (SCons SCT SNil))))+ sYearName = SCons SCY (SCons SCE (SCons SCA (SCons SCR SNil)))+ sGradeName+ = SCons SCG (SCons SCR (SCons SCA (SCons SCD (SCons SCE SNil))))+ sMajorName+ = SCons SCM (SCons SCA (SCons SCJ (SCons SCO (SCons SCR SNil))))+ sGradingSchema :: Sing GradingSchema+ sGradingSchema+ = SSch+ (SCons+ (SAttr sLastName SSTRING)+ (SCons+ (SAttr sFirstName SSTRING)+ (SCons+ (SAttr sYearName SNAT)+ (SCons+ (SAttr sGradeName SNAT) (SCons (SAttr sMajorName SBOOL) SNil)))))+ sNames :: Sing Names+ sNames+ = SSch+ (SCons+ (SAttr sFirstName SSTRING) (SCons (SAttr sLastName SSTRING) SNil))
+ tests/compile-and-dump/GradingClient/Main.hs view
@@ -0,0 +1,53 @@+{- GradingClient.hs++(c) Richard Eisenberg 2012+eir@cis.upenn.edu++This file accesses the database described in Database.hs and performs+some basic queries on it.++-}++{-# LANGUAGE TemplateHaskell, DataKinds #-}++module Main where++import Data.Singletons.TH+import Data.Singletons.List+import GradingClient.Database++$(singletons [d|+ lastName, firstName, yearName, gradeName, majorName :: [AChar]+ lastName = [CL, CA, CS, CT]+ firstName = [CF, CI, CR, CS, CT]+ yearName = [CY, CE, CA, CR]+ gradeName = [CG, CR, CA, CD, CE]+ majorName = [CM, CA, CJ, CO, CR]++ gradingSchema :: Schema+ gradingSchema = Sch [Attr lastName STRING,+ Attr firstName STRING,+ Attr yearName NAT,+ Attr gradeName NAT,+ Attr majorName BOOL]++ names :: Schema+ names = Sch [Attr firstName STRING,+ Attr lastName STRING]+ |])++main :: IO ()+main = do+ h <- connect "grades" sGradingSchema+ let ra = Read h++ allStudents <- query $ Project sNames ra+ putStrLn $ "Names of all students: " ++ (show allStudents) ++ "\n"++ majors <- query $ Select (Element sGradingSchema sMajorName) ra+ putStrLn $ "Students in major: " ++ (show majors) ++ "\n"++ b_students <-+ query $ Project sNames $+ Select (LessThan (Element sGradingSchema sGradeName) (LiteralNat 90)) ra+ putStrLn $ "Names of students with grade < 90: " ++ (show b_students) ++ "\n"
+ tests/compile-and-dump/InsertionSort/InsertionSortImp.ghc76.template view
@@ -0,0 +1,77 @@+InsertionSort/InsertionSortImp.hs:0:0: Splicing declarations+ singletons [d| data Nat = Zero | Succ Nat |]+ ======>+ InsertionSort/InsertionSortImp.hs:(0,0)-(0,0)+ data Nat = Zero | Succ Nat+ data instance Sing (z :: Nat)+ = z ~ Zero => SZero |+ forall (n :: Nat). z ~ Succ n => SSucc (Sing n)+ type SNat (z :: Nat) = Sing z+ instance SingKind (KProxy :: KProxy Nat) where+ type instance DemoteRep (KProxy :: KProxy Nat) = Nat+ fromSing SZero = Zero+ fromSing (SSucc b) = Succ (fromSing b)+ toSing Zero = SomeSing SZero+ toSing (Succ b)+ = case toSing b :: SomeSing (KProxy :: KProxy Nat) of {+ SomeSing c -> SomeSing (SSucc c) }+ instance SingI Zero where+ sing = SZero+ instance SingI n => SingI (Succ (n :: Nat)) where+ sing = SSucc sing+InsertionSort/InsertionSortImp.hs:0:0: Splicing declarations+ singletons+ [d| leq :: Nat -> Nat -> Bool+ leq Zero _ = True+ leq (Succ _) Zero = False+ leq (Succ a) (Succ b) = leq a b+ insert :: Nat -> [Nat] -> [Nat]+ insert n [] = [n]+ insert n (h : t)+ = if leq n h then (n : h : t) else h : (insert n t)+ insertionSort :: [Nat] -> [Nat]+ insertionSort [] = []+ insertionSort (h : t) = insert h (insertionSort t) |]+ ======>+ InsertionSort/InsertionSortImp.hs:(0,0)-(0,0)+ leq :: Nat -> Nat -> Bool+ leq Zero _ = True+ leq (Succ _) Zero = False+ leq (Succ a) (Succ b) = leq a b+ insert :: Nat -> [Nat] -> [Nat]+ insert n GHC.Types.[] = [n]+ insert n (h GHC.Types.: t)+ = if leq n h then+ (n GHC.Types.: (h GHC.Types.: t))+ else+ (h GHC.Types.: (insert n t))+ insertionSort :: [Nat] -> [Nat]+ insertionSort GHC.Types.[] = GHC.Types.[]+ insertionSort (h GHC.Types.: t) = insert h (insertionSort t)+ type instance Leq Zero z = True+ type instance Leq (Succ z) Zero = False+ type instance Leq (Succ a) (Succ b) = Leq a b+ type instance Insert n GHC.Types.[] = '[n]+ type instance Insert n (GHC.Types.: h t) =+ If (Leq n h) (GHC.Types.: n (GHC.Types.: h t)) (GHC.Types.: h (Insert n t))+ type instance InsertionSort GHC.Types.[] = GHC.Types.[]+ type instance InsertionSort (GHC.Types.: h t) =+ Insert h (InsertionSort t)+ type family Leq (a :: Nat) (a :: Nat) :: Bool+ type family Insert (a :: Nat) (a :: [Nat]) :: [Nat]+ type family InsertionSort (a :: [Nat]) :: [Nat]+ sLeq ::+ forall (t :: Nat) (t :: Nat). Sing t -> Sing t -> Sing (Leq t t)+ sLeq SZero _ = STrue+ sLeq (SSucc _) SZero = SFalse+ sLeq (SSucc a) (SSucc b) = sLeq a b+ sInsert ::+ forall (t :: Nat) (t :: [Nat]).+ Sing t -> Sing t -> Sing (Insert t t)+ sInsert n SNil = SCons n SNil+ sInsert n (SCons h t)+ = sIf (sLeq n h) (SCons n (SCons h t)) (SCons h (sInsert n t))+ sInsertionSort ::+ forall (t :: [Nat]). Sing t -> Sing (InsertionSort t)+ sInsertionSort SNil = SNil+ sInsertionSort (SCons h t) = sInsert h (sInsertionSort t)
+ tests/compile-and-dump/InsertionSort/InsertionSortImp.ghc78.template view
@@ -0,0 +1,75 @@+InsertionSort/InsertionSortImp.hs:0:0: Splicing declarations+ singletons [d| data Nat = Zero | Succ Nat |]+ ======>+ InsertionSort/InsertionSortImp.hs:(0,0)-(0,0)+ data Nat = Zero | Succ Nat+ data instance Sing (z :: Nat)+ = z ~ Zero => SZero |+ forall (n :: Nat). z ~ Succ n => SSucc (Sing n)+ type SNat (z :: Nat) = Sing z+ instance SingKind (KProxy :: KProxy Nat) where+ type DemoteRep (KProxy :: KProxy Nat) = Nat+ fromSing SZero = Zero+ fromSing (SSucc b) = Succ (fromSing b)+ toSing Zero = SomeSing SZero+ toSing (Succ b)+ = case toSing b :: SomeSing (KProxy :: KProxy Nat) of {+ SomeSing c -> SomeSing (SSucc c) }+ instance SingI Zero where+ sing = SZero+ instance SingI n => SingI (Succ (n :: Nat)) where+ sing = SSucc sing+InsertionSort/InsertionSortImp.hs:0:0: Splicing declarations+ singletons+ [d| leq :: Nat -> Nat -> Bool+ leq Zero _ = True+ leq (Succ _) Zero = False+ leq (Succ a) (Succ b) = leq a b+ insert :: Nat -> [Nat] -> [Nat]+ insert n [] = [n]+ insert n (h : t)+ = if leq n h then (n : h : t) else h : (insert n t)+ insertionSort :: [Nat] -> [Nat]+ insertionSort [] = []+ insertionSort (h : t) = insert h (insertionSort t) |]+ ======>+ InsertionSort/InsertionSortImp.hs:(0,0)-(0,0)+ leq :: Nat -> Nat -> Bool+ leq Zero _ = True+ leq (Succ _) Zero = False+ leq (Succ a) (Succ b) = leq a b+ insert :: Nat -> [Nat] -> [Nat]+ insert n GHC.Types.[] = [n]+ insert n (h GHC.Types.: t)+ = if leq n h then+ (n GHC.Types.: (h GHC.Types.: t))+ else+ (h GHC.Types.: (insert n t))+ insertionSort :: [Nat] -> [Nat]+ insertionSort GHC.Types.[] = []+ insertionSort (h GHC.Types.: t) = insert h (insertionSort t)+ type family Leq (a :: Nat) (a :: Nat) :: Bool where+ Leq Zero z = True+ Leq (Succ z) Zero = False+ Leq (Succ a) (Succ b) = Leq a b+ type family Insert (a :: Nat) (a :: [Nat]) :: [Nat] where+ Insert n GHC.Types.[] = '[n]+ Insert n ((GHC.Types.:) h t) = If (Leq n h) ((GHC.Types.:) n ((GHC.Types.:) h t)) ((GHC.Types.:) h (Insert n t))+ type family InsertionSort (a :: [Nat]) :: [Nat] where+ InsertionSort GHC.Types.[] = '[]+ InsertionSort ((GHC.Types.:) h t) = Insert h (InsertionSort t)+ sLeq ::+ forall (t :: Nat) (t :: Nat). Sing t -> Sing t -> Sing (Leq t t)+ sLeq SZero _ = STrue+ sLeq (SSucc _) SZero = SFalse+ sLeq (SSucc a) (SSucc b) = sLeq a b+ sInsert ::+ forall (t :: Nat) (t :: [Nat]).+ Sing t -> Sing t -> Sing (Insert t t)+ sInsert n SNil = SCons n SNil+ sInsert n (SCons h t)+ = sIf (sLeq n h) (SCons n (SCons h t)) (SCons h (sInsert n t))+ sInsertionSort ::+ forall (t :: [Nat]). Sing t -> Sing (InsertionSort t)+ sInsertionSort SNil = SNil+ sInsertionSort (SCons h t) = sInsert h (sInsertionSort t)
+ tests/compile-and-dump/InsertionSort/InsertionSortImp.hs view
@@ -0,0 +1,206 @@+{- InsertionSortImp.hs++(c) Richard Eisenberg 2012+eir@cis.upenn.edu++This file contains an implementation of insertion sort over natural numbers,+along with a Haskell proof that the sort algorithm is correct. The code below+uses a combination of GADTs and class instances to record the progress and+result of the proof.++Ideally, the GADTs would be defined so that the constructors take no explicit+parameters --- the information would all be encoded in the constraints to the+constructors. However, due to the nature of the permutation relation, a class+instance definition corresponding to the constructor PermIns would require+existentially-quantified type variables (the l2 variable in the declaration of+PermIns). Type variables in an instance constraint but not mentioned in the+instance head are inherently ambiguous. The compiler would never be able to+infer the value of the variables. Thus, it is not possible to make a class+PermutationC analogous to PermutationProof in the way that AscendingC is+analogous to AscendingProof. (Note that it may be possible to fundamentally+rewrite the inductive definition of the permutation relation to avoid+existentially-quantified variables. We have not attempted that here.)++If there were a way to offer an explicit dictionary when satisfying a constraint,+this problem could be avoided, as the variable in question could be made+unambiguous.++-}++{-# LANGUAGE IncoherentInstances #-}++module InsertionSort.InsertionSortImp where++import Data.Singletons.TH+import Data.Singletons.Prelude++-- We use the Dict data type from Edward Kmett's constraints package to be+-- able to return dictionaries from functions+import Data.Constraint++-- Natural numbers, defined with singleton counterparts+$(singletons [d|+ data Nat = Zero | Succ Nat+ |])++-- convenience functions for testing purposes+toNat :: Int -> Nat+toNat 0 = Zero+toNat n | n > 0 = Succ (toNat (n - 1))+toNat _ = error "Converting negative to Nat"++fromNat :: Nat -> Int+fromNat Zero = 0+fromNat (Succ n) = 1 + (fromNat n)++-- A less-than-or-equal relation among naturals+class (a :: Nat) :<=: (b :: Nat)+instance Zero :<=: a+instance (a :<=: b) => (Succ a) :<=: (Succ b)++-- A proof term asserting that a list of naturals is in ascending order+data AscendingProof :: [Nat] -> * where+ AscEmpty :: AscendingProof '[]+ AscOne :: AscendingProof '[n]+ AscCons :: (a :<=: b, AscendingC (b ': rest)) => AscendingProof (a ': b ': rest)++-- The class constraint (implicit parameter definition) corresponding to+-- AscendingProof+class AscendingC (lst :: [Nat]) where+ ascendingProof :: AscendingProof lst++-- The instances correspond to the constructors of AscendingProof+instance AscendingC '[] where+ ascendingProof = AscEmpty+instance AscendingC '[n] where+ ascendingProof = AscOne+instance (a :<=: b, AscendingC (b ': rest)) => AscendingC (a ': b ': rest) where+ ascendingProof = AscCons++-- A proof term asserting that l2 is the list produced when x is inserted+-- (anywhere) into list l1+data InsertionProof (x :: k) (l1 :: [k]) (l2 :: [k]) where+ InsHere :: InsertionProof x l (x ': l)+ InsLater :: InsertionC x l1 l2 => InsertionProof x (y ': l1) (y ': l2)++-- The class constraint corresponding to InsertionProof+class InsertionC (x :: k) (l1 :: [k]) (l2 :: [k]) where+ insertionProof :: InsertionProof x l1 l2++instance InsertionC x l (x ': l) where+ insertionProof = InsHere+instance InsertionC x l1 l2 => InsertionC x (y ': l1) (y ': l2) where+ insertionProof = InsLater++-- A proof term asserting that l1 and l2 are permutations of each other+data PermutationProof (l1 :: [k]) (l2 :: [k]) where+ PermId :: PermutationProof l l+ PermIns :: InsertionC x l2 l2' => PermutationProof l1 l2 ->+ PermutationProof (x ': l1) l2'++-- Here is the definition of insertion sort about which we will be reasoning:+$(singletons [d|+ leq :: Nat -> Nat -> Bool+ leq Zero _ = True+ leq (Succ _) Zero = False+ leq (Succ a) (Succ b) = leq a b++ insert :: Nat -> [Nat] -> [Nat]+ insert n [] = [n]+ insert n (h:t) = if leq n h then (n:h:t) else h:(insert n t)++ insertionSort :: [Nat] -> [Nat]+ insertionSort [] = []+ insertionSort (h:t) = insert h (insertionSort t)+ |])++-- A lemma that states if sLeq a b is STrue, then (a :<=: b)+-- This is necessary to convert from the boolean definition of <= to the+-- corresponding constraint+sLeq_true__le :: (Leq a b ~ True) => SNat a -> SNat b -> Dict (a :<=: b)+sLeq_true__le a b = case (a, b) of+ (SZero, SZero) -> Dict+ (SZero, SSucc _) -> Dict+ -- (SSucc _, SZero) -> undefined <== IMPOSSIBLE+ (SSucc a', SSucc b') -> case sLeq_true__le a' b' of+ Dict -> Dict+ _ -> error "type checking failed"++-- A lemma that states if sLeq a b is SFalse, then (b :<=: a)+sLeq_false__nle :: (Leq a b ~ False) => SNat a -> SNat b -> Dict (b :<=: a)+sLeq_false__nle a b = case (a, b) of+ -- (SZero, SZero) -> undefined <== IMPOSSIBLE+ -- (SZero, SSucc _) -> undefined <== IMPOSSIBLE+ (SSucc _, SZero) -> Dict+ (SSucc a', SSucc b') -> case sLeq_false__nle a' b' of+ Dict -> Dict+ _ -> error "type checking failed"++-- A lemma that states that inserting into an ascending list produces an+-- ascending list+insert_ascending :: forall n lst.+ AscendingC lst => SNat n -> SList lst -> Dict (AscendingC (Insert n lst))+insert_ascending n lst =+ case ascendingProof :: AscendingProof lst of+ AscEmpty -> Dict -- If lst is empty, then we're done+ AscOne -> case lst of -- If lst has one element...+ -- SNil -> undefined <== IMPOSSIBLE+ SCons h _ -> case sLeq n h of -- then check if n is <= h+ STrue -> case sLeq_true__le n h of Dict -> Dict -- if so, we're done+ SFalse -> case sLeq_false__nle n h of Dict -> Dict -- if not, we're done+ _ -> error "type checking failed"+ AscCons -> case lst of -- Otherwise, if lst is more than one element...+ -- SNil -> undefined <== IMPOSSIBLE+ SCons h t -> case sLeq n h of -- then check if n is <= h+ STrue -> case sLeq_true__le n h of Dict -> Dict -- if so, we're done+ SFalse -> case sLeq_false__nle n h of -- if not, things are harder...+ Dict -> case t of -- destruct t: lst is (h : h2 : t2)+ -- SNil -> undefined <== IMPOSSIBLE+ SCons h2 _ -> case sLeq n h2 of -- is n <= h2?+ STrue -> -- if so, we're done+ case sLeq_true__le n h2 of Dict -> Dict+ SFalse -> -- otherwise, show that (Insert n t) is sorted+ case insert_ascending n t of Dict -> Dict -- and we're done+ _ -> error "type checking failed"+ _ -> error "type checking failed"++-- A lemma that states that inserting n into lst produces a new list with n+-- inserted into lst.+insert_insertion :: SNat n -> SList lst -> Dict (InsertionC n lst (Insert n lst))+insert_insertion n lst =+ case lst of+ SNil -> Dict -- if lst is empty, we're done+ SCons h t -> case sLeq n h of -- otherwise, is n <= h?+ STrue -> Dict -- if so, we're done+ SFalse -> case insert_insertion n t of Dict -> Dict -- otherwise, recur++-- A lemma that states that the result of an insertion sort is in ascending order+insertionSort_ascending :: SList lst -> Dict (AscendingC (InsertionSort lst))+insertionSort_ascending lst = case lst of+ SNil -> Dict -- if the list is empty, we're done++ -- otherwise, we recur to find that insertionSort on t produces an ascending list,+ -- and then we use the fact that inserting into an ascending list produces an+ -- ascending list+ SCons h t -> case insertionSort_ascending t of+ Dict -> case insert_ascending h (sInsertionSort t) of Dict -> Dict++-- A lemma that states that the result of an insertion sort is a permutation+-- of its input+insertionSort_permutes :: SList lst -> PermutationProof lst (InsertionSort lst)+insertionSort_permutes lst = case lst of+ SNil -> PermId -- if the list is empty, we're done++ -- otherwise, we wish to use PermIns. We must know that t is a permutation of+ -- the insertion sort of t and that inserting h into the insertion sort of t+ -- works correctly:+ SCons h t ->+ case insert_insertion h (sInsertionSort t) of+ Dict -> PermIns (insertionSort_permutes t)++-- A theorem that states that the insertion sort of a list is both ascending+-- and a permutation of the original+insertionSort_correct :: SList lst -> (Dict (AscendingC (InsertionSort lst)),+ PermutationProof lst (InsertionSort lst))+insertionSort_correct lst = (insertionSort_ascending lst,+ insertionSort_permutes lst)
+ tests/compile-and-dump/Promote/NumArgs.ghc76.template view
@@ -0,0 +1,10 @@+Promote/NumArgs.hs:0:0: Splicing declarations+ promote+ [d| returnFunc :: Nat -> Nat -> Nat+ returnFunc _ = Succ |]+ ======>+ Promote/NumArgs.hs:(0,0)-(0,0)+ returnFunc :: Nat -> Nat -> Nat+ returnFunc _ = Succ+ type instance ReturnFunc z = Succ+ type family ReturnFunc (a :: Nat) :: Nat -> Nat
+ tests/compile-and-dump/Promote/NumArgs.ghc78.template view
@@ -0,0 +1,10 @@+Promote/NumArgs.hs:0:0: Splicing declarations+ promote+ [d| returnFunc :: Nat -> Nat -> Nat+ returnFunc _ = Succ |]+ ======>+ Promote/NumArgs.hs:(0,0)-(0,0)+ returnFunc :: Nat -> Nat -> Nat+ returnFunc _ = Succ+ type family ReturnFunc (a :: Nat) :: Nat -> Nat where+ ReturnFunc z = Succ
+ tests/compile-and-dump/Promote/NumArgs.hs view
@@ -0,0 +1,12 @@+module Promote.NumArgs where++import Data.Singletons.TH+import Singletons.Nat++-- used to test the "num args" feature of promoteDec+-- remove this test once eta-expansion is implemented++$(promote [d|+ returnFunc :: Nat -> Nat -> Nat+ returnFunc _ = Succ+ |])
+ tests/compile-and-dump/Promote/PatternMatching.ghc76.template view
@@ -0,0 +1,65 @@+Promote/PatternMatching.hs:0:0: Splicing declarations+ promote+ [d| pr = Pair (Succ Zero) ([Zero])+ complex = Pair (Pair (Just Zero) Zero) False+ tuple = (False, Just Zero, True)+ aList = [Zero, Succ Zero, Succ (Succ Zero)]++ data Pair a b+ = Pair a b+ deriving (Show) |]+ ======>+ Promote/PatternMatching.hs:(0,0)-(0,0)+ data Pair a b+ = Pair a b+ deriving (Show)+ pr = Pair (Succ Zero) [Zero]+ complex = Pair (Pair (Just Zero) Zero) False+ tuple = (False, Just Zero, True)+ aList = [Zero, Succ Zero, Succ (Succ Zero)]+ type Pr = Pair (Succ Zero) '[Zero]+ type Complex = Pair (Pair (Just Zero) Zero) False+ type Tuple = '(False, Just Zero, True)+ type AList = '[Zero, Succ Zero, Succ (Succ Zero)]+Promote/PatternMatching.hs:0:0: Splicing declarations+ promote+ [d| Pair sz lz = pr+ Pair (Pair jz zz) fls = complex+ (tf, tjz, tt) = tuple+ [_, lsz, (Succ blimy)] = aList |]+ ======>+ Promote/PatternMatching.hs:(0,0)-(0,0)+ Pair sz lz = pr+ Pair (Pair jz zz) fls = complex+ (tf, tjz, tt) = tuple+ [_, lsz, Succ blimy] = aList+ type Sz = Extract_0123456789 Pr+ type Lz = Extract_0123456789 Pr+ type family Extract_0123456789 (a :: Pair a b) :: a+ type family Extract_0123456789 (a :: Pair a b) :: b+ type instance Extract_0123456789 (Pair a a) = a+ type instance Extract_0123456789 (Pair a a) = a+ type Jz = Extract_0123456789 (Extract_0123456789 Complex)+ type Zz = Extract_0123456789 (Extract_0123456789 Complex)+ type Fls = Extract_0123456789 Complex+ type family Extract_0123456789 (a :: Pair a b) :: a+ type family Extract_0123456789 (a :: Pair a b) :: b+ type instance Extract_0123456789 (Pair a a) = a+ type instance Extract_0123456789 (Pair a a) = a+ type family Extract_0123456789 (a :: Pair a b) :: a+ type family Extract_0123456789 (a :: Pair a b) :: b+ type instance Extract_0123456789 (Pair a a) = a+ type instance Extract_0123456789 (Pair a a) = a+ type Tf = Extract_0123456789 Tuple+ type Tjz = Extract_0123456789 Tuple+ type Tt = Extract_0123456789 Tuple+ type family Extract_0123456789 (a :: GHC.Tuple.(,,) a b c) :: a+ type family Extract_0123456789 (a :: GHC.Tuple.(,,) a b c) :: b+ type family Extract_0123456789 (a :: GHC.Tuple.(,,) a b c) :: c+ type instance Extract_0123456789 (GHC.Tuple.(,,) a a a) = a+ type instance Extract_0123456789 (GHC.Tuple.(,,) a a a) = a+ type instance Extract_0123456789 (GHC.Tuple.(,,) a a a) = a+ type Lsz = Head (Tail AList)+ type Blimy = Extract_0123456789 (Head (Tail (Tail AList)))+ type family Extract_0123456789 (a :: Nat) :: Nat+ type instance Extract_0123456789 (Succ a) = a
+ tests/compile-and-dump/Promote/PatternMatching.ghc78.template view
@@ -0,0 +1,65 @@+Promote/PatternMatching.hs:0:0: Splicing declarations+ promote+ [d| pr = Pair (Succ Zero) ([Zero])+ complex = Pair (Pair (Just Zero) Zero) False+ tuple = (False, Just Zero, True)+ aList = [Zero, Succ Zero, Succ (Succ Zero)]++ data Pair a b+ = Pair a b+ deriving (Show) |]+ ======>+ Promote/PatternMatching.hs:(0,0)-(0,0)+ data Pair a b+ = Pair a b+ deriving (Show)+ pr = Pair (Succ Zero) [Zero]+ complex = Pair (Pair (Just Zero) Zero) False+ tuple = (False, Just Zero, True)+ aList = [Zero, Succ Zero, Succ (Succ Zero)]+ type Pr = Pair (Succ Zero) '[Zero]+ type Complex = Pair (Pair (Just Zero) Zero) False+ type Tuple = '(False, Just Zero, True)+ type AList = '[Zero, Succ Zero, Succ (Succ Zero)]+Promote/PatternMatching.hs:0:0: Splicing declarations+ promote+ [d| Pair sz lz = pr+ Pair (Pair jz zz) fls = complex+ (tf, tjz, tt) = tuple+ [_, lsz, (Succ blimy)] = aList |]+ ======>+ Promote/PatternMatching.hs:(0,0)-(0,0)+ Pair sz lz = pr+ Pair (Pair jz zz) fls = complex+ (tf, tjz, tt) = tuple+ [_, lsz, Succ blimy] = aList+ type Sz = Extract_0123456789 Pr+ type Lz = Extract_0123456789 Pr+ type family Extract_0123456789 (a :: Pair a b) :: a+ type family Extract_0123456789 (a :: Pair a b) :: b+ type instance Extract_0123456789 (Pair a a) = a+ type instance Extract_0123456789 (Pair a a) = a+ type Jz = Extract_0123456789 (Extract_0123456789 Complex)+ type Zz = Extract_0123456789 (Extract_0123456789 Complex)+ type Fls = Extract_0123456789 Complex+ type family Extract_0123456789 (a :: Pair a b) :: a+ type family Extract_0123456789 (a :: Pair a b) :: b+ type instance Extract_0123456789 (Pair a a) = a+ type instance Extract_0123456789 (Pair a a) = a+ type family Extract_0123456789 (a :: Pair a b) :: a+ type family Extract_0123456789 (a :: Pair a b) :: b+ type instance Extract_0123456789 (Pair a a) = a+ type instance Extract_0123456789 (Pair a a) = a+ type Tf = Extract_0123456789 Tuple+ type Tjz = Extract_0123456789 Tuple+ type Tt = Extract_0123456789 Tuple+ type family Extract_0123456789 (a :: GHC.Tuple.(,,) a b c) :: a+ type family Extract_0123456789 (a :: GHC.Tuple.(,,) a b c) :: b+ type family Extract_0123456789 (a :: GHC.Tuple.(,,) a b c) :: c+ type instance Extract_0123456789 (GHC.Tuple.(,,) a a a) = a+ type instance Extract_0123456789 (GHC.Tuple.(,,) a a a) = a+ type instance Extract_0123456789 (GHC.Tuple.(,,) a a a) = a+ type Lsz = Head (Tail AList)+ type Blimy = Extract_0123456789 (Head (Tail (Tail AList)))+ type family Extract_0123456789 (a :: Nat) :: Nat+ type instance Extract_0123456789 (Succ a) = a
+ tests/compile-and-dump/Promote/PatternMatching.hs view
@@ -0,0 +1,20 @@+module Promote.PatternMatching where++import Data.Singletons.TH+import Data.Singletons.Prelude+import Singletons.Nat++$(promote [d|+ data Pair a b = Pair a b deriving Show+ pr = Pair (Succ Zero) ([Zero])+ complex = Pair (Pair (Just Zero) Zero) False+ tuple = (False, Just Zero, True)+ aList = [Zero, Succ Zero, Succ (Succ Zero)]+ |])++$(promote [d|+ Pair sz lz = pr+ Pair (Pair jz zz) fls = complex+ (tf, tjz, tt) = tuple+ [_, lsz, (Succ blimy)] = aList+ |])
+ tests/compile-and-dump/Singletons/AtPattern.ghc76.template view
@@ -0,0 +1,16 @@+Singletons/AtPattern.hs:0:0: Splicing declarations+ singletons+ [d| maybePlus :: Maybe Nat -> Maybe Nat+ maybePlus (Just n) = Just (plus (Succ Zero) n)+ maybePlus foo@Nothing = foo |]+ ======>+ Singletons/AtPattern.hs:(0,0)-(0,0)+ maybePlus :: Maybe Nat -> Maybe Nat+ maybePlus (Just n) = Just (plus (Succ Zero) n)+ maybePlus foo@Nothing = foo+ type instance MaybePlus (Just n) = Just (Plus (Succ Zero) n)+ type instance MaybePlus Nothing = Nothing+ type family MaybePlus (a :: Maybe Nat) :: Maybe Nat+ sMaybePlus :: forall (t :: Maybe Nat). Sing t -> Sing (MaybePlus t)+ sMaybePlus (SJust n) = SJust (sPlus (SSucc SZero) n)+ sMaybePlus foo@SNothing = foo
+ tests/compile-and-dump/Singletons/AtPattern.ghc78.template view
@@ -0,0 +1,16 @@+Singletons/AtPattern.hs:0:0: Splicing declarations+ singletons+ [d| maybePlus :: Maybe Nat -> Maybe Nat+ maybePlus (Just n) = Just (plus (Succ Zero) n)+ maybePlus foo@Nothing = foo |]+ ======>+ Singletons/AtPattern.hs:(0,0)-(0,0)+ maybePlus :: Maybe Nat -> Maybe Nat+ maybePlus (Just n) = Just (plus (Succ Zero) n)+ maybePlus foo@Nothing = foo+ type family MaybePlus (a :: Maybe Nat) :: Maybe Nat where+ MaybePlus (Just n) = Just (Plus (Succ Zero) n)+ MaybePlus Nothing = Nothing+ sMaybePlus :: forall (t :: Maybe Nat). Sing t -> Sing (MaybePlus t)+ sMaybePlus (SJust n) = SJust (sPlus (SSucc SZero) n)+ sMaybePlus foo@SNothing = foo
+ tests/compile-and-dump/Singletons/AtPattern.hs view
@@ -0,0 +1,11 @@+module Singletons.AtPattern where++import Data.Singletons.TH+import Data.Singletons.Maybe+import Singletons.Nat++$(singletons [d|+ maybePlus :: Maybe Nat -> Maybe Nat+ maybePlus (Just n) = Just (plus (Succ Zero) n)+ maybePlus foo@Nothing = foo+ |])
+ tests/compile-and-dump/Singletons/BadPlus.ghc76.template view
@@ -0,0 +1,2 @@+Singletons/BadPlus.hs:0:0:+ No type signature for functions: "badPlus"; cannot promote or make singletons.
+ tests/compile-and-dump/Singletons/BadPlus.ghc78.template view
@@ -0,0 +1,2 @@+Singletons/BadPlus.hs:0:0:+ No type signature for functions: "badPlus"; cannot promote or make singletons.
+ tests/compile-and-dump/Singletons/BadPlus.hs view
@@ -0,0 +1,11 @@+module Singletons.BadPlus where++import Data.Singletons.TH+import Singletons.Nat++-- Test whether a declaration without type signature is not singletonized.++$(singletons [d|+ badPlus Zero m = m+ badPlus (Succ n) m = Succ (plus n m)+ |])
+ tests/compile-and-dump/Singletons/BoxUnBox.ghc76.template view
@@ -0,0 +1,28 @@+Singletons/BoxUnBox.hs:0:0: Splicing declarations+ singletons+ [d| unBox :: Box a -> a+ unBox (FBox a) = a++ data Box a = FBox a |]+ ======>+ Singletons/BoxUnBox.hs:(0,0)-(0,0)+ data Box a = FBox a+ unBox :: forall a. Box a -> a+ unBox (FBox a) = a+ type instance UnBox (FBox a) = a+ type family UnBox (a :: Box a) :: a+ data instance Sing (z :: Box a)+ = forall (n :: a). z ~ FBox n => SFBox (Sing n)+ type SBox (z :: Box a) = Sing z+ instance SingKind (KProxy :: KProxy a) =>+ SingKind (KProxy :: KProxy (Box a)) where+ type instance DemoteRep (KProxy :: KProxy (Box a)) =+ Box (DemoteRep (KProxy :: KProxy a))+ fromSing (SFBox b) = FBox (fromSing b)+ toSing (FBox b)+ = case toSing b :: SomeSing (KProxy :: KProxy a) of {+ SomeSing c -> SomeSing (SFBox c) }+ instance SingI n => SingI (FBox (n :: a)) where+ sing = SFBox sing+ sUnBox :: forall (t :: Box a). Sing t -> Sing (UnBox t)+ sUnBox (SFBox a) = a
+ tests/compile-and-dump/Singletons/BoxUnBox.ghc78.template view
@@ -0,0 +1,27 @@+Singletons/BoxUnBox.hs:0:0: Splicing declarations+ singletons+ [d| unBox :: Box a -> a+ unBox (FBox a) = a++ data Box a = FBox a |]+ ======>+ Singletons/BoxUnBox.hs:(0,0)-(0,0)+ data Box a = FBox a+ unBox :: forall a. Box a -> a+ unBox (FBox a) = a+ type family UnBox (a :: Box a) :: a where+ UnBox (FBox a) = a+ data instance Sing (z :: Box a)+ = forall (n :: a). z ~ FBox n => SFBox (Sing n)+ type SBox (z :: Box a) = Sing z+ instance SingKind (KProxy :: KProxy a) =>+ SingKind (KProxy :: KProxy (Box a)) where+ type DemoteRep (KProxy :: KProxy (Box a)) = Box (DemoteRep (KProxy :: KProxy a))+ fromSing (SFBox b) = FBox (fromSing b)+ toSing (FBox b)+ = case toSing b :: SomeSing (KProxy :: KProxy a) of {+ SomeSing c -> SomeSing (SFBox c) }+ instance SingI n => SingI (FBox (n :: a)) where+ sing = SFBox sing+ sUnBox :: forall (t :: Box a). Sing t -> Sing (UnBox t)+ sUnBox (SFBox a) = a
+ tests/compile-and-dump/Singletons/BoxUnBox.hs view
@@ -0,0 +1,9 @@+module Singletons.BoxUnBox where++import Data.Singletons.TH++$(singletons [d|+ data Box a = FBox a+ unBox :: Box a -> a+ unBox (FBox a) = a+ |])
+ tests/compile-and-dump/Singletons/Contains.ghc76.template view
@@ -0,0 +1,19 @@+Singletons/Contains.hs:0:0: Splicing declarations+ singletons+ [d| contains :: Eq a => a -> [a] -> Bool+ contains _ [] = False+ contains elt (h : t) = (elt == h) || (contains elt t) |]+ ======>+ Singletons/Contains.hs:(0,0)-(0,0)+ contains :: forall a. Eq a => a -> [a] -> Bool+ contains _ GHC.Types.[] = False+ contains elt (h GHC.Types.: t) = ((elt == h) || (contains elt t))+ type instance Contains z GHC.Types.[] = False+ type instance Contains elt (GHC.Types.: h t) =+ :|| (:== elt h) (Contains elt t)+ type family Contains (a :: a) (a :: [a]) :: Bool+ sContains ::+ forall (t :: a) (t :: [a]). SEq (KProxy :: KProxy a) =>+ Sing t -> Sing t -> Sing (Contains t t)+ sContains _ SNil = SFalse+ sContains elt (SCons h t) = (%:||) ((%:==) elt h) (sContains elt t)
+ tests/compile-and-dump/Singletons/Contains.ghc78.template view
@@ -0,0 +1,18 @@+Singletons/Contains.hs:0:0: Splicing declarations+ singletons+ [d| contains :: Eq a => a -> [a] -> Bool+ contains _ [] = False+ contains elt (h : t) = (elt == h) || (contains elt t) |]+ ======>+ Singletons/Contains.hs:(0,0)-(0,0)+ contains :: forall a. Eq a => a -> [a] -> Bool+ contains _ GHC.Types.[] = False+ contains elt (h GHC.Types.: t) = ((elt == h) || (contains elt t))+ type family Contains (a :: a) (a :: [a]) :: Bool where+ Contains z GHC.Types.[] = False+ Contains elt ((GHC.Types.:) h t) = (:||) ((:==) elt h) (Contains elt t)+ sContains ::+ forall (t :: a) (t :: [a]). SEq (KProxy :: KProxy a) =>+ Sing t -> Sing t -> Sing (Contains t t)+ sContains _ SNil = SFalse+ sContains elt (SCons h t) = (%:||) ((%:==) elt h) (sContains elt t)
+ tests/compile-and-dump/Singletons/Contains.hs view
@@ -0,0 +1,13 @@+module Singletons.Contains where++import Data.Singletons.TH+import Data.Singletons.List+import Data.Singletons.Bool++-- polimorphic function with context++$(singletons [d|+ contains :: Eq a => a -> [a] -> Bool+ contains _ [] = False+ contains elt (h:t) = (elt == h) || (contains elt t)+ |])
+ tests/compile-and-dump/Singletons/DataValues.ghc76.template view
@@ -0,0 +1,46 @@+Singletons/DataValues.hs:0:0: Splicing declarations+ singletons+ [d| pr = Pair (Succ Zero) ([Zero])+ complex = Pair (Pair (Just Zero) Zero) False+ tuple = (False, Just Zero, True)+ aList = [Zero, Succ Zero, Succ (Succ Zero)]++ data Pair a b+ = Pair a b+ deriving (Show) |]+ ======>+ Singletons/DataValues.hs:(0,0)-(0,0)+ data Pair a b+ = Pair a b+ deriving (Show)+ pr = Pair (Succ Zero) [Zero]+ complex = Pair (Pair (Just Zero) Zero) False+ tuple = (False, Just Zero, True)+ aList = [Zero, Succ Zero, Succ (Succ Zero)]+ type Pr = Pair (Succ Zero) '[Zero]+ type Complex = Pair (Pair (Just Zero) Zero) False+ type Tuple = '(False, Just Zero, True)+ type AList = '[Zero, Succ Zero, Succ (Succ Zero)]+ data instance Sing (z :: Pair a b)+ = forall (n :: a) (n :: b). z ~ Pair n n => SPair (Sing n) (Sing n)+ type SPair (z :: Pair a b) = Sing z+ instance (SingKind (KProxy :: KProxy a),+ SingKind (KProxy :: KProxy b)) =>+ SingKind (KProxy :: KProxy (Pair a b)) where+ type instance DemoteRep (KProxy :: KProxy (Pair a b)) =+ Pair (DemoteRep (KProxy :: KProxy a)) (DemoteRep (KProxy :: KProxy b))+ fromSing (SPair b b) = Pair (fromSing b) (fromSing b)+ toSing (Pair b b)+ = case+ (toSing b :: SomeSing (KProxy :: KProxy a),+ toSing b :: SomeSing (KProxy :: KProxy b))+ of {+ (SomeSing c, SomeSing c) -> SomeSing (SPair c c) }+ instance (SingI n, SingI n) => SingI (Pair (n :: a) (n :: b)) where+ sing = SPair sing sing+ sPr = SPair (SSucc SZero) (SCons SZero SNil)+ sComplex = SPair (SPair (SJust SZero) SZero) SFalse+ sTuple = STuple3 SFalse (SJust SZero) STrue+ sAList+ = SCons+ SZero (SCons (SSucc SZero) (SCons (SSucc (SSucc SZero)) SNil))
+ tests/compile-and-dump/Singletons/DataValues.ghc78.template view
@@ -0,0 +1,45 @@+Singletons/DataValues.hs:0:0: Splicing declarations+ singletons+ [d| pr = Pair (Succ Zero) ([Zero])+ complex = Pair (Pair (Just Zero) Zero) False+ tuple = (False, Just Zero, True)+ aList = [Zero, Succ Zero, Succ (Succ Zero)]++ data Pair a b+ = Pair a b+ deriving (Show) |]+ ======>+ Singletons/DataValues.hs:(0,0)-(0,0)+ data Pair a b+ = Pair a b+ deriving (Show)+ pr = Pair (Succ Zero) [Zero]+ complex = Pair (Pair (Just Zero) Zero) False+ tuple = (False, Just Zero, True)+ aList = [Zero, Succ Zero, Succ (Succ Zero)]+ type Pr = Pair (Succ Zero) '[Zero]+ type Complex = Pair (Pair (Just Zero) Zero) False+ type Tuple = '(False, Just Zero, True)+ type AList = '[Zero, Succ Zero, Succ (Succ Zero)]+ data instance Sing (z :: Pair a b)+ = forall (n :: a) (n :: b). z ~ Pair n n => SPair (Sing n) (Sing n)+ type SPair (z :: Pair a b) = Sing z+ instance (SingKind (KProxy :: KProxy a),+ SingKind (KProxy :: KProxy b)) =>+ SingKind (KProxy :: KProxy (Pair a b)) where+ type DemoteRep (KProxy :: KProxy (Pair a b)) = Pair (DemoteRep (KProxy :: KProxy a)) (DemoteRep (KProxy :: KProxy b))+ fromSing (SPair b b) = Pair (fromSing b) (fromSing b)+ toSing (Pair b b)+ = case+ (toSing b :: SomeSing (KProxy :: KProxy a),+ toSing b :: SomeSing (KProxy :: KProxy b))+ of {+ (SomeSing c, SomeSing c) -> SomeSing (SPair c c) }+ instance (SingI n, SingI n) => SingI (Pair (n :: a) (n :: b)) where+ sing = SPair sing sing+ sPr = SPair (SSucc SZero) (SCons SZero SNil)+ sComplex = SPair (SPair (SJust SZero) SZero) SFalse+ sTuple = STuple3 SFalse (SJust SZero) STrue+ sAList+ = SCons+ SZero (SCons (SSucc SZero) (SCons (SSucc (SSucc SZero)) SNil))
+ tests/compile-and-dump/Singletons/DataValues.hs view
@@ -0,0 +1,18 @@+module Singletons.DataValues where++import Data.Singletons.TH+import Data.Singletons.Prelude+import Singletons.Nat++$(singletons [d|+ data Pair a b = Pair a b deriving Show++ pr = Pair (Succ Zero) ([Zero])++ complex = Pair (Pair (Just Zero) Zero) False++ tuple = (False, Just Zero, True)++ aList = [Zero, Succ Zero, Succ (Succ Zero)]++ |])
+ tests/compile-and-dump/Singletons/Empty.ghc76.template view
@@ -0,0 +1,15 @@+Singletons/Empty.hs:0:0: Splicing declarations+ singletons [d| data Empty |]+ ======>+ Singletons/Empty.hs:(0,0)-(0,0)+ data Empty+ data instance Sing (z :: Empty)+ type SEmpty (z :: Empty) = Sing z+ instance SingKind (KProxy :: KProxy Empty) where+ type instance DemoteRep (KProxy :: KProxy Empty) = Empty+ fromSing z+ = case z of {+ _ -> error "Empty case reached -- this should be impossible" }+ toSing z+ = case z of {+ _ -> error "Empty case reached -- this should be impossible" }
+ tests/compile-and-dump/Singletons/Empty.ghc78.template view
@@ -0,0 +1,15 @@+Singletons/Empty.hs:0:0: Splicing declarations+ singletons [d| data Empty |]+ ======>+ Singletons/Empty.hs:(0,0)-(0,0)+ data Empty+ data instance Sing (z :: Empty)+ type SEmpty (z :: Empty) = Sing z+ instance SingKind (KProxy :: KProxy Empty) where+ type DemoteRep (KProxy :: KProxy Empty) = Empty+ fromSing z+ = case z of {+ _ -> error "Empty case reached -- this should be impossible" }+ toSing z+ = case z of {+ _ -> error "Empty case reached -- this should be impossible" }
+ tests/compile-and-dump/Singletons/Empty.hs view
@@ -0,0 +1,7 @@+module Singletons.Empty where++import Data.Singletons.TH++$(singletons [d|+ data Empty+ |])
+ tests/compile-and-dump/Singletons/EqInstances.ghc76.template view
@@ -0,0 +1,17 @@+Singletons/EqInstances.hs:0:0: Splicing declarations+ singEqInstances [''Foo, ''Empty]+ ======>+ Singletons/EqInstances.hs:0:0:+ instance SEq (KProxy :: KProxy Foo) where+ %:== SFLeaf SFLeaf = STrue+ %:== SFLeaf (:%+: _ _) = SFalse+ %:== (:%+: _ _) SFLeaf = SFalse+ %:== (:%+: a a) (:%+: b b) = (%:&&) ((%:==) a b) ((%:==) a b)+ type instance (:==) FLeaf FLeaf = True+ type instance (:==) FLeaf (:+: b b) = False+ type instance (:==) (:+: a a) FLeaf = False+ type instance (:==) (:+: a a) (:+: b b) = :&& (:== a b) (:== a b)+ instance SEq (KProxy :: KProxy Empty) where+ %:== a _+ = case a of {+ _ -> error "Empty case reached -- this should be impossible" }
+ tests/compile-and-dump/Singletons/EqInstances.ghc78.template view
@@ -0,0 +1,22 @@+Singletons/EqInstances.hs:0:0: Splicing declarations+ singEqInstances [''Foo, ''Empty]+ ======>+ Singletons/EqInstances.hs:0:0:+ instance SEq (KProxy :: KProxy Foo) where+ (%:==) SFLeaf SFLeaf = STrue+ (%:==) SFLeaf ((:%+:) _ _) = SFalse+ (%:==) ((:%+:) _ _) SFLeaf = SFalse+ (%:==) ((:%+:) a a) ((:%+:) b b) = (%:&&) ((%:==) a b) ((%:==) a b)+ type family Equals_0123456789 (a :: Foo) (b :: Foo) :: Bool where+ Equals_0123456789 FLeaf FLeaf = True+ Equals_0123456789 ((:+:) a a) ((:+:) b b) = (:&&) ((==) a b) ((==) a b)+ Equals_0123456789 (a :: Foo) (b :: Foo) = False+ type instance (==) (a :: Foo) (b :: Foo) = Equals_0123456789 a b+ instance SEq (KProxy :: KProxy Empty) where+ (%:==) a _+ = case a of {+ _ -> error "Empty case reached -- this should be impossible" }+ type family Equals_0123456789 (a :: Empty)+ (b :: Empty) :: Bool where+ Equals_0123456789 (a :: Empty) (b :: Empty) = False+ type instance (==) (a :: Empty) (b :: Empty) = Equals_0123456789 a b
+ tests/compile-and-dump/Singletons/EqInstances.hs view
@@ -0,0 +1,8 @@+module Singletons.EqInstances where++import Data.Singletons.TH+import Data.Singletons.Bool+import Singletons.Empty+import Singletons.Operators++$(singEqInstances [''Foo, ''Empty])
+ tests/compile-and-dump/Singletons/HigherOrder.ghc76.template view
@@ -0,0 +1,33 @@+Singletons/HigherOrder.hs:0:0: Splicing declarations+ singletons+ [d| map :: (a -> b) -> [a] -> [b]+ map _ [] = []+ map f (h : t) = (f h) : (map f t)+ liftMaybe :: (a -> b) -> Maybe a -> Maybe b+ liftMaybe f (Just x) = Just (f x)+ liftMaybe _ Nothing = Nothing |]+ ======>+ Singletons/HigherOrder.hs:(0,0)-(0,0)+ map :: forall a b. (a -> b) -> [a] -> [b]+ map _ GHC.Types.[] = GHC.Types.[]+ map f (h GHC.Types.: t) = ((f h) GHC.Types.: (map f t))+ liftMaybe :: forall a b. (a -> b) -> Maybe a -> Maybe b+ liftMaybe f (Just x) = Just (f x)+ liftMaybe _ Nothing = Nothing+ type instance Map z GHC.Types.[] = GHC.Types.[]+ type instance Map f (GHC.Types.: h t) = GHC.Types.: (f h) (Map f t)+ type instance LiftMaybe f (Just x) = Just (f x)+ type instance LiftMaybe z Nothing = Nothing+ type family Map (a :: a -> b) (a :: [a]) :: [b]+ type family LiftMaybe (a :: a -> b) (a :: Maybe a) :: Maybe b+ sMap ::+ forall (t :: a -> b) (t :: [a]).+ (forall (t :: a). Sing t -> Sing (t t)) -> Sing t -> Sing (Map t t)+ sMap _ SNil = SNil+ sMap f (SCons h t) = SCons (f h) (sMap f t)+ sLiftMaybe ::+ forall (t :: a -> b) (t :: Maybe a).+ (forall (t :: a). Sing t -> Sing (t t))+ -> Sing t -> Sing (LiftMaybe t t)+ sLiftMaybe f (SJust x) = SJust (f x)+ sLiftMaybe _ SNothing = SNothing
+ tests/compile-and-dump/Singletons/HigherOrder.ghc78.template view
@@ -0,0 +1,33 @@+Singletons/HigherOrder.hs:0:0: Splicing declarations+ singletons+ [d| map :: (a -> b) -> [a] -> [b]+ map _ [] = []+ map f (h : t) = (f h) : (map f t)+ liftMaybe :: (a -> b) -> Maybe a -> Maybe b+ liftMaybe f (Just x) = Just (f x)+ liftMaybe _ Nothing = Nothing |]+ ======>+ Singletons/HigherOrder.hs:(0,0)-(0,0)+ map :: forall a b. (a -> b) -> [a] -> [b]+ map _ GHC.Types.[] = []+ map f (h GHC.Types.: t) = ((f h) GHC.Types.: (map f t))+ liftMaybe :: forall a b. (a -> b) -> Maybe a -> Maybe b+ liftMaybe f (Just x) = Just (f x)+ liftMaybe _ Nothing = Nothing+ type family Map (a :: a -> b) (a :: [a]) :: [b] where+ Map z GHC.Types.[] = '[]+ Map f ((GHC.Types.:) h t) = (GHC.Types.:) (f h) (Map f t)+ type family LiftMaybe (a :: a -> b) (a :: Maybe a) :: Maybe b where+ LiftMaybe f (Just x) = Just (f x)+ LiftMaybe z Nothing = Nothing+ sMap ::+ forall (t :: a -> b) (t :: [a]).+ (forall (t :: a). Sing t -> Sing (t t)) -> Sing t -> Sing (Map t t)+ sMap _ SNil = SNil+ sMap f (SCons h t) = SCons (f h) (sMap f t)+ sLiftMaybe ::+ forall (t :: a -> b) (t :: Maybe a).+ (forall (t :: a). Sing t -> Sing (t t))+ -> Sing t -> Sing (LiftMaybe t t)+ sLiftMaybe f (SJust x) = SJust (f x)+ sLiftMaybe _ SNothing = SNothing
+ tests/compile-and-dump/Singletons/HigherOrder.hs view
@@ -0,0 +1,15 @@+module Singletons.HigherOrder where++import Data.Singletons.TH+import Data.Singletons.List+import Data.Singletons.Maybe++$(singletons [d|+ map :: (a -> b) -> [a] -> [b]+ map _ [] = []+ map f (h:t) = (f h) : (map f t)++ liftMaybe :: (a -> b) -> Maybe a -> Maybe b+ liftMaybe f (Just x) = Just (f x)+ liftMaybe _ Nothing = Nothing+ |])
+ tests/compile-and-dump/Singletons/Maybe.ghc76.template view
@@ -0,0 +1,53 @@+Singletons/Maybe.hs:0:0: Splicing declarations+ singletons+ [d| data Maybe a+ = Nothing | Just a+ deriving (Eq, Show) |]+ ======>+ Singletons/Maybe.hs:(0,0)-(0,0)+ data Maybe a+ = Nothing | Just a+ deriving (Eq, Show)+ type instance (:==) Nothing Nothing = True+ type instance (:==) Nothing (Just b) = False+ type instance (:==) (Just a) Nothing = False+ type instance (:==) (Just a) (Just b) = :== a b+ data instance Sing (z :: Maybe a)+ = z ~ Nothing => SNothing |+ forall (n :: a). z ~ Just n => SJust (Sing n)+ type SMaybe (z :: Maybe a) = Sing z+ instance SingKind (KProxy :: KProxy a) =>+ SingKind (KProxy :: KProxy (Maybe a)) where+ type instance DemoteRep (KProxy :: KProxy (Maybe a)) =+ Maybe (DemoteRep (KProxy :: KProxy a))+ fromSing SNothing = Nothing+ fromSing (SJust b) = Just (fromSing b)+ toSing Nothing = SomeSing SNothing+ toSing (Just b)+ = case toSing b :: SomeSing (KProxy :: KProxy a) of {+ SomeSing c -> SomeSing (SJust c) }+ instance SEq (KProxy :: KProxy a) =>+ SEq (KProxy :: KProxy (Maybe a)) where+ %:== SNothing SNothing = STrue+ %:== SNothing (SJust _) = SFalse+ %:== (SJust _) SNothing = SFalse+ %:== (SJust a) (SJust b) = (%:==) a b+ instance SDecide (KProxy :: KProxy a) =>+ SDecide (KProxy :: KProxy (Maybe a)) where+ %~ SNothing SNothing = Proved Refl+ %~ SNothing (SJust _)+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ (SJust _) SNothing+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ (SJust a) (SJust b)+ = case (%~) a b of {+ Proved Refl -> Proved Refl+ Disproved contra -> Disproved (\ Refl -> contra Refl) }+ instance SingI Nothing where+ sing = SNothing+ instance SingI n => SingI (Just (n :: a)) where+ sing = SJust sing
+ tests/compile-and-dump/Singletons/Maybe.ghc78.template view
@@ -0,0 +1,54 @@+Singletons/Maybe.hs:0:0: Splicing declarations+ singletons+ [d| data Maybe a+ = Nothing | Just a+ deriving (Eq, Show) |]+ ======>+ Singletons/Maybe.hs:(0,0)-(0,0)+ data Maybe a+ = Nothing | Just a+ deriving (Eq, Show)+ type family Equals_0123456789 (a :: Maybe k)+ (b :: Maybe k) :: Bool where+ Equals_0123456789 Nothing Nothing = True+ Equals_0123456789 (Just a) (Just b) = (==) a b+ Equals_0123456789 (a :: Maybe k) (b :: Maybe k) = False+ type instance (==) (a :: Maybe k) (b :: Maybe k) = Equals_0123456789 a b+ data instance Sing (z :: Maybe a)+ = z ~ Nothing => SNothing |+ forall (n :: a). z ~ Just n => SJust (Sing n)+ type SMaybe (z :: Maybe a) = Sing z+ instance SingKind (KProxy :: KProxy a) =>+ SingKind (KProxy :: KProxy (Maybe a)) where+ type DemoteRep (KProxy :: KProxy (Maybe a)) = Maybe (DemoteRep (KProxy :: KProxy a))+ fromSing SNothing = Nothing+ fromSing (SJust b) = Just (fromSing b)+ toSing Nothing = SomeSing SNothing+ toSing (Just b)+ = case toSing b :: SomeSing (KProxy :: KProxy a) of {+ SomeSing c -> SomeSing (SJust c) }+ instance SEq (KProxy :: KProxy a) =>+ SEq (KProxy :: KProxy (Maybe a)) where+ (%:==) SNothing SNothing = STrue+ (%:==) SNothing (SJust _) = SFalse+ (%:==) (SJust _) SNothing = SFalse+ (%:==) (SJust a) (SJust b) = (%:==) a b+ instance SDecide (KProxy :: KProxy a) =>+ SDecide (KProxy :: KProxy (Maybe a)) where+ (%~) SNothing SNothing = Proved Refl+ (%~) SNothing (SJust _)+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) (SJust _) SNothing+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) (SJust a) (SJust b)+ = case (%~) a b of {+ Proved Refl -> Proved Refl+ Disproved contra -> Disproved (\ Refl -> contra Refl) }+ instance SingI Nothing where+ sing = SNothing+ instance SingI n => SingI (Just (n :: a)) where+ sing = SJust sing
+ tests/compile-and-dump/Singletons/Maybe.hs view
@@ -0,0 +1,7 @@+module Singletons.Maybe where++import Data.Singletons.TH++$(singletons [d|+ data Maybe a = Nothing | Just a deriving (Eq, Show)+ |])
+ tests/compile-and-dump/Singletons/Nat.ghc76.template view
@@ -0,0 +1,79 @@+Singletons/Nat.hs:0:0: Splicing declarations+ singletons++ [d| plus :: Nat -> Nat -> Nat+ plus Zero m = m+ plus (Succ n) m = Succ (plus n m)++ pred :: Nat -> Nat+ pred Zero = Zero+ pred (Succ n) = n++ data Nat+ where+ Zero :: Nat+ Succ :: Nat -> Nat+ deriving (Eq, Show, Read) |]+ ======>+ Singletons/Nat.hs:(0,0)-(0,0)+ data Nat+ = Zero | Succ Nat+ deriving (Eq, Show, Read)+ plus :: Nat -> Nat -> Nat+ plus Zero m = m+ plus (Succ n) m = Succ (plus n m)+ pred :: Nat -> Nat+ pred Zero = Zero+ pred (Succ n) = n+ type instance (:==) Zero Zero = True+ type instance (:==) Zero (Succ b) = False+ type instance (:==) (Succ a) Zero = False+ type instance (:==) (Succ a) (Succ b) = :== a b+ type instance Plus Zero m = m+ type instance Plus (Succ n) m = Succ (Plus n m)+ type instance Pred Zero = Zero+ type instance Pred (Succ n) = n+ type family Plus (a :: Nat) (a :: Nat) :: Nat+ type family Pred (a :: Nat) :: Nat+ data instance Sing (z :: Nat)+ = z ~ Zero => SZero |+ forall (n :: Nat). z ~ Succ n => SSucc (Sing n)+ type SNat (z :: Nat) = Sing z+ instance SingKind (KProxy :: KProxy Nat) where+ type instance DemoteRep (KProxy :: KProxy Nat) = Nat+ fromSing SZero = Zero+ fromSing (SSucc b) = Succ (fromSing b)+ toSing Zero = SomeSing SZero+ toSing (Succ b)+ = case toSing b :: SomeSing (KProxy :: KProxy Nat) of {+ SomeSing c -> SomeSing (SSucc c) }+ instance SEq (KProxy :: KProxy Nat) where+ %:== SZero SZero = STrue+ %:== SZero (SSucc _) = SFalse+ %:== (SSucc _) SZero = SFalse+ %:== (SSucc a) (SSucc b) = (%:==) a b+ instance SDecide (KProxy :: KProxy Nat) where+ %~ SZero SZero = Proved Refl+ %~ SZero (SSucc _)+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ (SSucc _) SZero+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ (SSucc a) (SSucc b)+ = case (%~) a b of {+ Proved Refl -> Proved Refl+ Disproved contra -> Disproved (\ Refl -> contra Refl) }+ instance SingI Zero where+ sing = SZero+ instance SingI n => SingI (Succ (n :: Nat)) where+ sing = SSucc sing+ sPlus ::+ forall (t :: Nat) (t :: Nat). Sing t -> Sing t -> Sing (Plus t t)+ sPlus SZero m = m+ sPlus (SSucc n) m = SSucc (sPlus n m)+ sPred :: forall (t :: Nat). Sing t -> Sing (Pred t)+ sPred SZero = SZero+ sPred (SSucc n) = n
+ tests/compile-and-dump/Singletons/Nat.ghc78.template view
@@ -0,0 +1,80 @@+Singletons/Nat.hs:0:0: Splicing declarations+ singletons++ [d| plus :: Nat -> Nat -> Nat+ plus Zero m = m+ plus (Succ n) m = Succ (plus n m)++ pred :: Nat -> Nat+ pred Zero = Zero+ pred (Succ n) = n++ data Nat+ where+ Zero :: Nat+ Succ :: Nat -> Nat+ deriving (Eq, Show, Read) |]+ ======>+ Singletons/Nat.hs:(0,0)-(0,0)+ data Nat+ = Zero | Succ Nat+ deriving (Eq, Show, Read)+ plus :: Nat -> Nat -> Nat+ plus Zero m = m+ plus (Succ n) m = Succ (plus n m)+ pred :: Nat -> Nat+ pred Zero = Zero+ pred (Succ n) = n+ type family Equals_0123456789 (a :: Nat) (b :: Nat) :: Bool where+ Equals_0123456789 Zero Zero = True+ Equals_0123456789 (Succ a) (Succ b) = (==) a b+ Equals_0123456789 (a :: Nat) (b :: Nat) = False+ type instance (==) (a :: Nat) (b :: Nat) = Equals_0123456789 a b+ type family Plus (a :: Nat) (a :: Nat) :: Nat where+ Plus Zero m = m+ Plus (Succ n) m = Succ (Plus n m)+ type family Pred (a :: Nat) :: Nat where+ Pred Zero = Zero+ Pred (Succ n) = n+ data instance Sing (z :: Nat)+ = z ~ Zero => SZero |+ forall (n :: Nat). z ~ Succ n => SSucc (Sing n)+ type SNat (z :: Nat) = Sing z+ instance SingKind (KProxy :: KProxy Nat) where+ type DemoteRep (KProxy :: KProxy Nat) = Nat+ fromSing SZero = Zero+ fromSing (SSucc b) = Succ (fromSing b)+ toSing Zero = SomeSing SZero+ toSing (Succ b)+ = case toSing b :: SomeSing (KProxy :: KProxy Nat) of {+ SomeSing c -> SomeSing (SSucc c) }+ instance SEq (KProxy :: KProxy Nat) where+ (%:==) SZero SZero = STrue+ (%:==) SZero (SSucc _) = SFalse+ (%:==) (SSucc _) SZero = SFalse+ (%:==) (SSucc a) (SSucc b) = (%:==) a b+ instance SDecide (KProxy :: KProxy Nat) where+ (%~) SZero SZero = Proved Refl+ (%~) SZero (SSucc _)+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) (SSucc _) SZero+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) (SSucc a) (SSucc b)+ = case (%~) a b of {+ Proved Refl -> Proved Refl+ Disproved contra -> Disproved (\ Refl -> contra Refl) }+ instance SingI Zero where+ sing = SZero+ instance SingI n => SingI (Succ (n :: Nat)) where+ sing = SSucc sing+ sPlus ::+ forall (t :: Nat) (t :: Nat). Sing t -> Sing t -> Sing (Plus t t)+ sPlus SZero m = m+ sPlus (SSucc n) m = SSucc (sPlus n m)+ sPred :: forall (t :: Nat). Sing t -> Sing (Pred t)+ sPred SZero = SZero+ sPred (SSucc n) = n
+ tests/compile-and-dump/Singletons/Nat.hs view
@@ -0,0 +1,18 @@+module Singletons.Nat where++import Data.Singletons.TH++$(singletons [d|+ data Nat where+ Zero :: Nat+ Succ :: Nat -> Nat+ deriving (Eq, Show, Read)++ plus :: Nat -> Nat -> Nat+ plus Zero m = m+ plus (Succ n) m = Succ (plus n m)++ pred :: Nat -> Nat+ pred Zero = Zero+ pred (Succ n) = n+ |])
+ tests/compile-and-dump/Singletons/Operators.ghc76.template view
@@ -0,0 +1,56 @@+Singletons/Operators.hs:0:0: Splicing declarations+ singletons+ [d| child :: Foo -> Foo+ child FLeaf = FLeaf+ child (a :+: _) = a+ + :: Nat -> Nat -> Nat+ Zero + m = m+ (Succ n) + m = Succ (n + m)++ data Foo+ where+ FLeaf :: Foo+ :+: :: Foo -> Foo -> Foo |]+ ======>+ Singletons/Operators.hs:(0,0)-(0,0)+ data Foo = FLeaf | (:+:) Foo Foo+ child :: Foo -> Foo+ child FLeaf = FLeaf+ child (a :+: _) = a+ + :: Nat -> Nat -> Nat+ + Zero m = m+ + (Succ n) m = Succ (n + m)+ type instance Child FLeaf = FLeaf+ type instance Child (:+: a z) = a+ type instance (:+) Zero m = m+ type instance (:+) (Succ n) m = Succ (:+ n m)+ type family Child (a :: Foo) :: Foo+ type family (:+) (a :: Nat) (a :: Nat) :: Nat+ data instance Sing (z :: Foo)+ = z ~ FLeaf => SFLeaf |+ forall (n :: Foo) (n :: Foo). z ~ :+: n n =>+ (:%+:) (Sing n) (Sing n)+ type SFoo (z :: Foo) = Sing z+ instance SingKind (KProxy :: KProxy Foo) where+ type instance DemoteRep (KProxy :: KProxy Foo) = Foo+ fromSing SFLeaf = FLeaf+ fromSing (:%+: b b) = (:+:) (fromSing b) (fromSing b)+ toSing FLeaf = SomeSing SFLeaf+ toSing (:+: b b)+ = case+ (toSing b :: SomeSing (KProxy :: KProxy Foo),+ toSing b :: SomeSing (KProxy :: KProxy Foo))+ of {+ (SomeSing c, SomeSing c) -> SomeSing ((:%+:) c c) }+ instance SingI FLeaf where+ sing = SFLeaf+ instance (SingI n, SingI n) =>+ SingI (:+: (n :: Foo) (n :: Foo)) where+ sing = (:%+:) sing sing+ sChild :: forall (t :: Foo). Sing t -> Sing (Child t)+ sChild SFLeaf = SFLeaf+ sChild (:%+: a _) = a+ %:+ ::+ forall (t :: Nat) (t :: Nat). Sing t -> Sing t -> Sing (:+ t t)+ %:+ SZero m = m+ %:+ (SSucc n) m = SSucc ((%:+) n m)
+ tests/compile-and-dump/Singletons/Operators.ghc78.template view
@@ -0,0 +1,56 @@+Singletons/Operators.hs:0:0: Splicing declarations+ singletons+ [d| child :: Foo -> Foo+ child FLeaf = FLeaf+ child (a :+: _) = a+ (+) :: Nat -> Nat -> Nat+ Zero + m = m+ (Succ n) + m = Succ (n + m)++ data Foo+ where+ FLeaf :: Foo+ :+: :: Foo -> Foo -> Foo |]+ ======>+ Singletons/Operators.hs:(0,0)-(0,0)+ data Foo = FLeaf | (:+:) Foo Foo+ child :: Foo -> Foo+ child FLeaf = FLeaf+ child (a :+: _) = a+ (+) :: Nat -> Nat -> Nat+ (+) Zero m = m+ (+) (Succ n) m = Succ (n + m)+ type family Child (a :: Foo) :: Foo where+ Child FLeaf = FLeaf+ Child ((:+:) a z) = a+ type family (:+) (a :: Nat) (a :: Nat) :: Nat where+ (:+) Zero m = m+ (:+) (Succ n) m = Succ ((:+) n m)+ data instance Sing (z :: Foo)+ = z ~ FLeaf => SFLeaf |+ forall (n :: Foo) (n :: Foo). z ~ (:+:) n n =>+ (:%+:) (Sing n) (Sing n)+ type SFoo (z :: Foo) = Sing z+ instance SingKind (KProxy :: KProxy Foo) where+ type DemoteRep (KProxy :: KProxy Foo) = Foo+ fromSing SFLeaf = FLeaf+ fromSing ((:%+:) b b) = (:+:) (fromSing b) (fromSing b)+ toSing FLeaf = SomeSing SFLeaf+ toSing ((:+:) b b)+ = case+ (toSing b :: SomeSing (KProxy :: KProxy Foo),+ toSing b :: SomeSing (KProxy :: KProxy Foo))+ of {+ (SomeSing c, SomeSing c) -> SomeSing ((:%+:) c c) }+ instance SingI FLeaf where+ sing = SFLeaf+ instance (SingI n, SingI n) =>+ SingI ((:+:) (n :: Foo) (n :: Foo)) where+ sing = (:%+:) sing sing+ sChild :: forall (t :: Foo). Sing t -> Sing (Child t)+ sChild SFLeaf = SFLeaf+ sChild ((:%+:) a _) = a+ (%:+) ::+ forall (t :: Nat) (t :: Nat). Sing t -> Sing t -> Sing ((:+) t t)+ (%:+) SZero m = m+ (%:+) (SSucc n) m = SSucc ((%:+) n m)
+ tests/compile-and-dump/Singletons/Operators.hs view
@@ -0,0 +1,18 @@+module Singletons.Operators where++import Data.Singletons.TH+import Singletons.Nat++$(singletons [d|+ data Foo where+ FLeaf :: Foo+ (:+:) :: Foo -> Foo -> Foo++ child :: Foo -> Foo+ child FLeaf = FLeaf+ child (a :+: _) = a++ (+) :: Nat -> Nat -> Nat+ Zero + m = m+ (Succ n) + m = Succ (n + m)+ |])
+ tests/compile-and-dump/Singletons/Star.ghc76.template view
@@ -0,0 +1,188 @@+Singletons/Star.hs:0:0: Splicing declarations+ singletonStar [''Nat, ''Int, ''String, ''Maybe, ''Vec]+ ======>+ Singletons/Star.hs:0:0:+ data Rep+ = Nat | Int | String | Maybe Rep | Vec Rep Nat+ deriving (Eq, Show, Read)+ type instance (:==) Nat Nat = True+ type instance (:==) Nat Int = False+ type instance (:==) Nat String = False+ type instance (:==) Nat (Maybe b) = False+ type instance (:==) Nat (Vec b b) = False+ type instance (:==) Int Nat = False+ type instance (:==) Int Int = True+ type instance (:==) Int String = False+ type instance (:==) Int (Maybe b) = False+ type instance (:==) Int (Vec b b) = False+ type instance (:==) String Nat = False+ type instance (:==) String Int = False+ type instance (:==) String String = True+ type instance (:==) String (Maybe b) = False+ type instance (:==) String (Vec b b) = False+ type instance (:==) (Maybe a) Nat = False+ type instance (:==) (Maybe a) Int = False+ type instance (:==) (Maybe a) String = False+ type instance (:==) (Maybe a) (Maybe b) = :== a b+ type instance (:==) (Maybe a) (Vec b b) = False+ type instance (:==) (Vec a a) Nat = False+ type instance (:==) (Vec a a) Int = False+ type instance (:==) (Vec a a) String = False+ type instance (:==) (Vec a a) (Maybe b) = False+ type instance (:==) (Vec a a) (Vec b b) = :&& (:== a b) (:== a b)+ data instance Sing (z :: *)+ = z ~ Nat => SNat |+ z ~ Int => SInt |+ z ~ String => SString |+ forall (n :: *). z ~ Maybe n => SMaybe (Sing n) |+ forall (n :: *) (n :: Nat). z ~ Vec n n => SVec (Sing n) (Sing n)+ type SRep (z :: *) = Sing z+ instance SingKind (KProxy :: KProxy *) where+ type instance DemoteRep (KProxy :: KProxy *) = Rep+ fromSing SNat = Nat+ fromSing SInt = Int+ fromSing SString = String+ fromSing (SMaybe b) = Maybe (fromSing b)+ fromSing (SVec b b) = Vec (fromSing b) (fromSing b)+ toSing Nat = SomeSing SNat+ toSing Int = SomeSing SInt+ toSing String = SomeSing SString+ toSing (Maybe b)+ = case toSing b :: SomeSing (KProxy :: KProxy *) of {+ SomeSing c -> SomeSing (SMaybe c) }+ toSing (Vec b b)+ = case+ (toSing b :: SomeSing (KProxy :: KProxy *),+ toSing b :: SomeSing (KProxy :: KProxy Nat))+ of {+ (SomeSing c, SomeSing c) -> SomeSing (SVec c c) }+ instance SEq (KProxy :: KProxy *) where+ %:== SNat SNat = STrue+ %:== SNat SInt = SFalse+ %:== SNat SString = SFalse+ %:== SNat (SMaybe _) = SFalse+ %:== SNat (SVec _ _) = SFalse+ %:== SInt SNat = SFalse+ %:== SInt SInt = STrue+ %:== SInt SString = SFalse+ %:== SInt (SMaybe _) = SFalse+ %:== SInt (SVec _ _) = SFalse+ %:== SString SNat = SFalse+ %:== SString SInt = SFalse+ %:== SString SString = STrue+ %:== SString (SMaybe _) = SFalse+ %:== SString (SVec _ _) = SFalse+ %:== (SMaybe _) SNat = SFalse+ %:== (SMaybe _) SInt = SFalse+ %:== (SMaybe _) SString = SFalse+ %:== (SMaybe a) (SMaybe b) = (%:==) a b+ %:== (SMaybe _) (SVec _ _) = SFalse+ %:== (SVec _ _) SNat = SFalse+ %:== (SVec _ _) SInt = SFalse+ %:== (SVec _ _) SString = SFalse+ %:== (SVec _ _) (SMaybe _) = SFalse+ %:== (SVec a a) (SVec b b) = (%:&&) ((%:==) a b) ((%:==) a b)+ instance SDecide (KProxy :: KProxy *) where+ %~ SNat SNat = Proved Refl+ %~ SNat SInt+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SNat SString+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SNat (SMaybe _)+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SNat (SVec _ _)+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SInt SNat+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SInt SInt = Proved Refl+ %~ SInt SString+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SInt (SMaybe _)+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SInt (SVec _ _)+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SString SNat+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SString SInt+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SString SString = Proved Refl+ %~ SString (SMaybe _)+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ SString (SVec _ _)+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ (SMaybe _) SNat+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ (SMaybe _) SInt+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ (SMaybe _) SString+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ (SMaybe a) (SMaybe b)+ = case (%~) a b of {+ Proved Refl -> Proved Refl+ Disproved contra -> Disproved (\ Refl -> contra Refl) }+ %~ (SMaybe _) (SVec _ _)+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ (SVec _ _) SNat+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ (SVec _ _) SInt+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ (SVec _ _) SString+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ (SVec _ _) (SMaybe _)+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ %~ (SVec a a) (SVec b b)+ = case ((%~) a b, (%~) a b) of {+ (Proved Refl, Proved Refl) -> Proved Refl+ (Disproved contra, _) -> Disproved (\ Refl -> contra Refl)+ (_, Disproved contra) -> Disproved (\ Refl -> contra Refl) }+ instance SingI Nat where+ sing = SNat+ instance SingI Int where+ sing = SInt+ instance SingI String where+ sing = SString+ instance SingI n => SingI (Maybe (n :: *)) where+ sing = SMaybe sing+ instance (SingI n, SingI n) =>+ SingI (Vec (n :: *) (n :: Nat)) where+ sing = SVec sing sing
+ tests/compile-and-dump/Singletons/Star.ghc78.template view
@@ -0,0 +1,142 @@+Singletons/Star.hs:0:0: Splicing declarations+ singletonStar [''Nat, ''Int, ''String, ''Maybe, ''Vec]+ ======>+ Singletons/Star.hs:0:0:+ data Rep+ = Nat | Int | String | Maybe Rep | Vec Rep Nat+ deriving (Eq, Show, Read)+ instance SDecide (KProxy :: KProxy *) where+ (%~) SNat SNat = Proved Refl+ (%~) SNat SInt+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SNat SString+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SNat (SMaybe _)+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SNat (SVec _ _)+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SInt SNat+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SInt SInt = Proved Refl+ (%~) SInt SString+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SInt (SMaybe _)+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SInt (SVec _ _)+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SString SNat+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SString SInt+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SString SString = Proved Refl+ (%~) SString (SMaybe _)+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) SString (SVec _ _)+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) (SMaybe _) SNat+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) (SMaybe _) SInt+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) (SMaybe _) SString+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) (SMaybe a) (SMaybe b)+ = case (%~) a b of {+ Proved Refl -> Proved Refl+ Disproved contra -> Disproved (\ Refl -> contra Refl) }+ (%~) (SMaybe _) (SVec _ _)+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) (SVec _ _) SNat+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) (SVec _ _) SInt+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) (SVec _ _) SString+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) (SVec _ _) (SMaybe _)+ = Disproved+ (\case {+ _ -> error "Empty case reached -- this should be impossible" })+ (%~) (SVec a a) (SVec b b)+ = case ((%~) a b, (%~) a b) of {+ (Proved Refl, Proved Refl) -> Proved Refl+ (Disproved contra, _) -> Disproved (\ Refl -> contra Refl)+ (_, Disproved contra) -> Disproved (\ Refl -> contra Refl) }+ instance SEq (KProxy :: KProxy *) where+ (%:==) a b+ = case (%~) a b of {+ Proved Refl -> STrue+ Disproved _ -> Unsafe.Coerce.unsafeCoerce SFalse }+ data instance Sing (z :: *)+ = z ~ Nat => SNat |+ z ~ Int => SInt |+ z ~ String => SString |+ forall (n :: *). z ~ Maybe n => SMaybe (Sing n) |+ forall (n :: *) (n :: Nat). z ~ Vec n n => SVec (Sing n) (Sing n)+ type SRep (z :: *) = Sing z+ instance SingKind (KProxy :: KProxy *) where+ type DemoteRep (KProxy :: KProxy *) = Rep+ fromSing SNat = Nat+ fromSing SInt = Int+ fromSing SString = String+ fromSing (SMaybe b) = Maybe (fromSing b)+ fromSing (SVec b b) = Vec (fromSing b) (fromSing b)+ toSing Nat = SomeSing SNat+ toSing Int = SomeSing SInt+ toSing String = SomeSing SString+ toSing (Maybe b)+ = case toSing b :: SomeSing (KProxy :: KProxy *) of {+ SomeSing c -> SomeSing (SMaybe c) }+ toSing (Vec b b)+ = case+ (toSing b :: SomeSing (KProxy :: KProxy *),+ toSing b :: SomeSing (KProxy :: KProxy Nat))+ of {+ (SomeSing c, SomeSing c) -> SomeSing (SVec c c) }+ instance SingI Nat where+ sing = SNat+ instance SingI Int where+ sing = SInt+ instance SingI String where+ sing = SString+ instance SingI n => SingI (Maybe (n :: *)) where+ sing = SMaybe sing+ instance (SingI n, SingI n) =>+ SingI (Vec (n :: *) (n :: Nat)) where+ sing = SVec sing sing
+ tests/compile-and-dump/Singletons/Star.hs view
@@ -0,0 +1,14 @@+{-# OPTIONS_GHC -fno-warn-unused-imports #-}++module Singletons.Star where++import Data.Singletons.Prelude+import Data.Singletons.Decide+import Data.Singletons.CustomStar+import Singletons.Nat++data Vec :: * -> Nat -> * where+ VNil :: Vec a Zero+ VCons :: a -> Vec a n -> Vec a (Succ n)++$(singletonStar [''Nat, ''Int, ''String, ''Maybe, ''Vec])
+ tests/compile-and-dump/buildGoldenFiles.awk view
@@ -0,0 +1,1 @@+/INSERT/{while((getline line < $2) > 0 ){if(line !~ /INSERT/){print line}}close($2);next}1