-------------------------------------------------------------------------------- -------------------------------------------------------------------------------- --Module : Type.Set --Author : Daniel Schüssler --License : BSD3 --Copyright : Daniel Schüssler -- --Maintainer : Daniel Schüssler --Stability : Experimental --Portability : Uses various GHC extensions -- -------------------------------------------------------------------------------- --Description : -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- {-# LANGUAGE CPP #-} {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE IncoherentInstances #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE NoMonomorphismRestriction #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE TypeSynonymInstances #-} {-# OPTIONS #-} {-# OPTIONS -fwarn-missing-signatures #-} -- | -- -- * Sets are encoded as certain types of kind @* -> *@ -- -- * A value of type @S X@ is a proof that the type @X@ is a member of @S@ -- module Type.Set where import Data.Type.Equality import Type.Logic import Type.Dummies import Data.Monoid import Control.Monad import Helper import Control.Applicative import Data.Typeable.Extras import Data.Data hiding (DataType) {----------------------------- emacs snippets for the funny characters (move behind the final parenthesis, press C-x C-e) (progn (yas/define 'haskell-mode "subs" ":⊆:") (yas/define 'haskell-mode "union" ":∪:") (yas/define 'haskell-mode "inter" ":∩:") (yas/define 'haskell-mode "times" ":×:") (yas/define 'haskell-mode "elt" ":∈:") (yas/define 'haskell-mode "elt1" "::∈:") (yas/define 'haskell-mode "circ" ":○:") (yas/define 'haskell-mode "Sigma" "Σ") (yas/define 'haskell-mode "Pi" "Π") (yas/define 'haskell-mode "-->" ":~>:") (yas/define 'haskell-mode "--->" ":~~>:") ) -----------------------------} #include "../Defs.hs" -- * Subsets, equality type a :∈: set = set a infix 4 :∈: -- | Represents a proof that @set1@ is a subset of @set2@ data (set1 :: SET) :⊆: (set2 :: SET) where Subset :: (forall a. a :∈: set1 -> a :∈: set2) -> set1 :⊆: set2 -- | Coercion from subset to superset scoerce :: (set1 :⊆: set2) -> a :∈: set1 -> a :∈: set2 scoerce (Subset x) = x infix 4 :⊆: type Subset = (:⊆:) -- | Extensional equality of sets data (set1 :: (SET)) :==: (set2 :: (SET)) = SetEq (set1 :⊆: set2) (set2 :⊆: set1) infix 4 :==: instance Fact (set1 :⊆: set2 -> a :∈: set1 -> a :∈: set2) where auto = scoerce -- | Coercion using a set equality ecoerce :: (s1 :==: s2) -> a :∈: s1 -> a :∈: s2 ecoerce (SetEq p _) = scoerce p -- | Coercion using a set equality (flipped) ecoerceFlip :: (s1 :==: s2) -> a :∈: s2 -> a :∈: s1 ecoerceFlip (SetEq _ q) = scoerce q subsetRefl :: s :⊆: s subsetRefl = Subset id subsetTrans :: (s1 :⊆: s2 -> s2 :⊆: s3 -> s1 :⊆: s3); subsetTrans p1 p2 = Subset (scoerce p2 . scoerce p1) setEqRefl :: s :==: s; setEqRefl = SetEq subsetRefl subsetRefl setEqSym :: s1 :==: s2 -> s2 :==: s1; setEqSym (SetEq p1 p2) = SetEq p2 p1 setEqTrans :: (s1 :==: s2 -> s2 :==: s3 -> s1 :==: s3); setEqTrans (SetEq p1 p2) (SetEq q1 q2) = SetEq (p1 `subsetTrans` q1) (q2 `subsetTrans` p2) type Singleton a = (:=:) a instance Fact (Singleton a a) where auto = Refl instance (Fact (a :∈: set)) => (Fact (Singleton a :⊆: set)) where auto = Subset (\Refl -> auto) -- * Union, intersection, difference -- | Binary union data (s1 :: SET) :∪: (s2 :: SET) :: SET where Union :: Either (a :∈: s1) (a :∈: s2) -> (s1 :∪: s2) a elimUnion :: a :∈: (s1 :∪: s2) -> Either (a :∈: s1) (a :∈: s2) elimUnion (Union x) = x infixr 5 :∪: type Union = (:∪:) unionL :: s1 :⊆: (s1 :∪: s2) unionL = Subset (Union . Left) unionR :: s2 :⊆: (s1 :∪: s2) unionR = Subset (Union . Right) unionMinimal :: s1 :⊆: t -> s2 :⊆: t -> (s1 :∪: s2) :⊆: t unionMinimal p1 p2 = Subset (\(Union q) -> case q of Left q1 -> scoerce p1 q1 Right q2 -> scoerce p2 q2) unionIdempotent :: s :∪: s :==: s unionIdempotent = SetEq (unionMinimal auto auto) unionL instance (Fact (s1 :⊆: t), Fact (s2 :⊆: t)) => Fact (s1 :∪: s2 :⊆: t) where auto = unionMinimal auto auto -- | Binary intersection data ((s1 :: SET) :∩: (s2 :: SET)) :: SET where Inter :: a :∈: s1 -> a :∈: s2 -> (s1 :∩: s2) a elimInter :: a :∈: (s1 :∩: s2) -> (a :∈: s1, a :∈: s2) elimInter (Inter x y) = (x,y) interFst :: (s1 :∩: s2) :⊆: s1 interFst = Subset (fst . elimInter) interSnd :: (s1 :∩: s2) :⊆: s2 interSnd = Subset (snd . elimInter) infixr 6 :∩: type Inter = (:∩:) interMaximal :: (t :⊆: s1 -> t :⊆: s2 -> t :⊆: (s1 :∩: s2)) interMaximal p1 p2 = Subset (\q -> Inter (scoerce p1 q) (scoerce p2 q)) instance (Fact (t :⊆: s1), Fact (t :⊆: s2)) => Fact (t :⊆: (s1 :∩: s2)) where auto = interMaximal auto auto interIdempotent :: s :∩: s :==: s interIdempotent = SetEq interFst (interMaximal auto auto) -- | Union of a family data Unions (fam :: SET) :: SET where Unions :: Lower s :∈: fam -> a :∈: s -> Unions fam a elimUnions :: Unions fam a -> (forall s. Lower s :∈: fam -> a :∈: s -> r) -> r elimUnions (Unions p1 p2) k = k p1 p2 instance Fact (Lower s :∈: fam -> s :⊆: (Unions fam)) where auto p = Subset (Unions p) -- | Dependent sum data Σ (fam :: SET) :: SET where Σ :: Lower s :∈: fam -> a :∈: s -> Σ fam (Lower s, a) type DependentSum = Σ -- | Intersection of a family data Inters (fam :: SET) :: SET where Inters :: (forall s. (Lower s) :∈: fam -> a :∈: s) -> Inters fam a elimInters :: Inters fam a -> (Lower s) :∈: fam -> s a elimInters (Inters x) = x instance Fact ((Lower s) :∈: fam -> (Inters fam) :⊆: s ) where auto p = Subset (($ p) . elimInters) -- | Complement data Complement (s :: SET) :: SET where Complement :: Not (a :∈: s) -> Complement s a elimComplement :: a :∈: Complement s -> Not (a :∈: s) elimComplement (Complement x) = x type Disjoint s1 s2 = (s1 :∩: s2) :⊆: Empty complContradiction :: Not (s a, Complement s a) complContradiction (p, Complement q) = q p complEmpty :: Disjoint s (Complement s) complEmpty = Subset (elimFalsity . complContradiction . elimInter) complMaximal :: Disjoint s t -> (t :⊆: Complement s) complMaximal p = Subset (\q -> Complement (\r -> elimEmpty (p `scoerce` (Inter r q)))) -- | Set difference data Diff (s :: SET) (t :: SET) :: SET where Diff :: a :∈: s -> Not (a :∈: t) -> Diff s t a elimDiff :: a :∈: Diff s t -> (a :∈: s, Not (a :∈: t)) elimDiff (Diff x y) = (x,y) -- * Products -- | Binary products data (s1 :: SET) :×: (s2 :: SET) :: SET where (:×:) :: a :∈: s1 -> b :∈: s2 -> (s1 :×: s2) (a, b) infixr 6 :×: type Prod = (:×:) fstPrf :: (a, b) :∈: (s1 :×: s2) -> a :∈: s1; fstPrf (p :×: _) = p sndPrf :: (a, b) :∈: (s1 :×: s2) -> b :∈: s2; sndPrf (_ :×: q) = q -- | Product is monotonic wrt. subset inclusion prodMonotonic :: s1 :⊆: t1 -> s2 :⊆: t2 -> s1 :×: s2 :⊆: t1 :×: t2; prodMonotonic p1 p2 = Subset (\(q1 :×: q2) -> scoerce p1 q1 :×: scoerce p2 q2) -- * Particular sets -- | Empty set (barring cheating with 'undefined') data Empty :: SET where Empty :: (forall b. b) -> Empty a elimEmpty :: Empty a -> b elimEmpty (Empty x) = x emptySubset :: (Empty :⊆: s) emptySubset = Subset elimEmpty -- | Set of /all/ types of kind * data Univ :: SET where Univ :: Univ a univSubset :: (s :⊆: Univ) univSubset = Subset (const Univ) data FunctionType :: SET where FunctionType :: FunctionType (a -> b) functionType :: (a -> b) :∈: FunctionType functionType = FunctionType data KleisliType m :: SET where KleisliType :: KleisliType m (a -> m b) kleisliType :: (a -> m b) :∈: (KleisliType m) kleisliType = KleisliType data CoKleisliType w :: SET where CoKleisliType :: CoKleisliType w (w a -> b) coKleisliType :: (w a -> b) :∈: (CoKleisliType w) coKleisliType = CoKleisliType -- *** Sets from common typeclasses -- (yas/define 'haskell-mode "class-set" "data $1Type :: SET where $1Type :: $1 a => $1Type a\ninstance $1 a => Fact (a :∈: $1Type) where auto = $1Type\n$0") -- (yas/define 'haskell-mode "class-set1" "data $1Type :: SET where $1Type :: $1 a => $1Type (Lower a)\ninstance $1 a => Fact (Lower a :∈: $1Type) where auto = $1Type\n$0") data ShowType :: SET where ShowType :: Show a => ShowType a instance Show a => Fact (a :∈: ShowType) where auto = ShowType -- data ReflectShow a = ReflectShow (ShowType a) a -- instance Show (ReflectShow a) where show (ReflectShow ShowType a) = show a -- | Example application getShow :: a :∈: ShowType -> a -> String getShow ShowType = show data ReadType :: SET where ReadType :: Read a => ReadType a instance Read a => Fact (a :∈: ReadType) where auto = ReadType data EqType :: SET where EqType :: Eq a => EqType a instance Eq a => Fact (a :∈: EqType) where auto = EqType getEq :: a :∈: EqType -> a -> a -> Bool getEq EqType = (==) data OrdType :: SET where OrdType :: Ord a => OrdType a instance Ord a => Fact (a :∈: OrdType) where auto = OrdType getCompare :: a :∈: OrdType -> a -> a -> Ordering getCompare OrdType = compare data EnumType :: SET where EnumType :: Enum a => EnumType a instance Enum a => Fact (a :∈: EnumType) where auto = EnumType data BoundedType :: SET where BoundedType :: Bounded a => BoundedType a instance Bounded a => Fact (a :∈: BoundedType) where auto = BoundedType data NumType :: SET where NumType :: Num a => NumType a instance Num a => Fact (a :∈: NumType) where auto = NumType data IntegralType :: SET where IntegralType :: Integral a => IntegralType a instance Integral a => Fact (a :∈: IntegralType) where auto = IntegralType data MonoidType :: SET where MonoidType :: Monoid a => MonoidType a instance Monoid a => Fact (a :∈: MonoidType) where auto = MonoidType data FractionalType :: SET where FractionalType :: Fractional a => FractionalType a instance Fractional a => Fact (a :∈: FractionalType) where auto = FractionalType data TypeableType :: SET where TypeableType :: Typeable a => TypeableType a instance Typeable a => Fact (a :∈: TypeableType) where auto = TypeableType data DataType :: SET where DataType :: Data a => DataType a instance Data a => Fact (a :∈: DataType) where auto = DataType -- ** Kind (* -> *) data FunctorType :: SET where FunctorType :: Functor a => FunctorType (Lower a) instance Functor a => Fact (Lower a :∈: FunctorType) where auto = FunctorType getFmap :: Lower f :∈: FunctorType -> (a -> b) -> (f a -> f b) getFmap FunctorType = fmap data MonadType :: SET where MonadType :: Monad a => MonadType (Lower a) instance Monad a => Fact (Lower a :∈: MonadType) where auto = MonadType data MonadPlusType :: SET where MonadPlusType :: MonadPlus a => MonadPlusType (Lower a) instance MonadPlus a => Fact (Lower a :∈: MonadPlusType) where auto = MonadPlusType data ApplicativeType :: SET where ApplicativeType :: Applicative a => ApplicativeType (Lower a) instance Applicative a => Fact (Lower a :∈: ApplicativeType) where auto = ApplicativeType -- * Powerset -- | Membership of a set in a set representing a set of sets type a ::∈: set = set (Lower a) infix 4 ::∈: -- (yas/define 'haskell-mode "k2" "SET -> *") -- | Powerset data (Powerset (u :: SET)) :: SET where Powerset :: s :⊆: u -> Powerset u (Lower s) powersetWholeset :: u ::∈: Powerset u powersetWholeset = Powerset subsetRefl powersetEmpty :: Empty ::∈: Powerset u powersetEmpty = Powerset emptySubset powersetUnion :: s1 ::∈: Powerset u -> s2 ::∈: Powerset u -> (s1 :∪: s2) ::∈: Powerset u powersetUnion (Powerset p1) (Powerset p2) = Powerset (unionMinimal p1 p2) powersetInter :: s1 ::∈: Powerset u -> s2 ::∈: Powerset u -> (s1 :∩: s2) ::∈: Powerset u powersetInter (Powerset p1) (Powerset _) = Powerset (subsetTrans auto p1) powersetMonotonic :: (u1 :⊆: u2) -> s ::∈: Powerset u1 -> s ::∈: Powerset u2 powersetMonotonic p (Powerset q) = Powerset (Subset (scoerce p . scoerce q)) powersetClosedDownwards :: (s1 :⊆: s2) -> s2 ::∈: Powerset u -> s1 ::∈: Powerset u powersetClosedDownwards p (Powerset q) = Powerset (Subset (scoerce q . scoerce p)) -- * Misc autosubset :: Fact (s :⊆: t) => s :⊆: t autosubset = auto autoequality :: Fact (s :==: t) => s :==: t autoequality = auto data ProofSet (s :: SET) :: SET where ProofSet :: s x -> ProofSet s (s x) #define SUBCLASS(X,Y)\ instance Fact (X :⊆: Y) where\ auto = Subset (\ X -> Y ) SUBCLASS(OrdType,EqType) SUBCLASS(NumType,EqType) SUBCLASS(IntegralType,NumType) SUBCLASS(MonadPlusType,MonadType) -- instance ( Fact1 (s1 :⊆: s2) -- , Fact1 (s2 :⊆: s3)) -- => Fact (s1 :⊆: s3) where -- auto = subsetTrans auto auto -- * Unique existence of sets -- | Unique existence, unlowered data ExUniq1 (p :: SET -> *) where ExUniq1 :: p b -> (forall b'. p b' -> b :==: b') -> ExUniq1 p -- * From sets to the value level -- | @V s@ is the sum of all types @x@ such that @s x@ is provable. data V (s :: SET) where V :: s x -> x -> V s liftEq :: (s :⊆: EqType) -> (s :⊆: TypeableType) -> (V s -> V s -> Bool) liftEq s s2 (V px x) (V py y) = case ( s `scoerce` px , s `scoerce` py , s2 `scoerce` px , s2 `scoerce` py) of (EqType, EqType, TypeableType, TypeableType) -> dynEq x y instance ( ( Fact (s :⊆: EqType) , Fact (s :⊆: TypeableType) ) => Eq (V s) ) where (==) = liftEq auto auto liftCompare :: (s :⊆: OrdType) -> (s :⊆: TypeableType) -> (V s -> V s -> Ordering) liftCompare s s2 (V px x) (V py y) = case ( s `scoerce` px , s `scoerce` py , s2 `scoerce` px , s2 `scoerce` py) of (OrdType, OrdType, TypeableType, TypeableType) -> dynCompare x y instance ( ( Fact (s :⊆: OrdType) , Fact (s :⊆: TypeableType) , Eq (V s) ) => Ord (V s) ) where compare = liftCompare auto auto liftShowsPrec :: Typeable1 s => (s :⊆: ShowType) -> (s :⊆: TypeableType) -> (Int -> V s -> ShowS) liftShowsPrec s s2 prec (V px x) = case ( s `scoerce` px , s2 `scoerce` px ) of (ShowType, TypeableType) -> showParen (prec > 10) (showString "V " . showString "<< proof of " . shows (typeOf px) . showString " >> " . showsPrec 11 x) $(lemmata ''Fact [ 'fstPrf,'sndPrf,'prodMonotonic , 'complEmpty, 'complContradiction , 'elimEmpty, 'emptySubset , 'ecoerce,'ecoerceFlip , 'subsetRefl , 'subsetTrans,'setEqRefl,'setEqSym,'setEqTrans , 'univSubset, 'complMaximal , 'powersetClosedDownwards , 'powersetMonotonic , 'interMaximal, 'unionMinimal , 'functionType, 'kleisliType, 'coKleisliType , 'interFst, 'interSnd ,'unionL,'unionR ])