witness 0.2 → 0.3
raw patch · 19 files changed
+750/−538 lines, 19 filesdep +categoriesdep +constraintsdep +transformersdep −mtl
Dependencies added: categories, constraints, transformers
Dependencies removed: mtl
Files
- Data/Witness.hs +0/−33
- Data/Witness/Any.hs +0/−56
- Data/Witness/EqualType.hs +0/−17
- Data/Witness/List.hs +0/−86
- Data/Witness/Nat.hs +0/−53
- Data/Witness/Representative.hs +0/−72
- Data/Witness/SimpleWitness.hs +0/−15
- Data/Witness/Type.hs +0/−28
- Data/Witness/WitnessDict.hs +0/−63
- Data/Witness/WitnessFDict.hs +0/−63
- src/Data/Witness.hs +33/−0
- src/Data/Witness/Any.hs +39/−0
- src/Data/Witness/List.hs +358/−0
- src/Data/Witness/ListElement.hs +28/−0
- src/Data/Witness/Nat.hs +51/−0
- src/Data/Witness/Representative.hs +64/−0
- src/Data/Witness/WitnessDict.hs +63/−0
- src/Data/Witness/WitnessFDict.hs +63/−0
- witness.cabal +51/−52
− Data/Witness.hs
@@ -1,33 +0,0 @@-module Data.Witness-(- module Data.Witness.WitnessDict,- module Data.Witness.WitnessFDict,- module Data.Witness.Any,- module Data.Witness.Representative,- module Data.Witness.Type,- module Data.Witness.SimpleWitness,- module Data.Witness.EqualType,- module Data.Witness.Nat,- module Data.Witness.List,- module Data.Witness-) where-{- import Data.Witness.List;- import Data.Witness.Nat;- import Data.Witness.EqualType;- import Data.Witness.SimpleWitness;- import Data.Witness.Type;- import Data.Witness.Representative;- import Data.Witness.Any;- import Data.Witness.WitnessFDict;- import Data.Witness.WitnessDict;-- -- | See whether two represented and witnessed types are the same.- ;- matchIs :: (SimpleWitness w,Is w a,Is w b) => Type (w ()) -> Maybe (EqualType a b);- matchIs t = matchWitness (foo t) (foo t) where- {- foo :: (Is w a) => Type (w ()) -> w a;- foo _ = representative;- };-}
− Data/Witness/Any.hs
@@ -1,56 +0,0 @@-module Data.Witness.Any where-{- import Data.Witness.SimpleWitness;- import Data.Witness.EqualType;- import Data.Maybe;-- -- | Any value with a witness to it.- ;- data Any w = forall a. MkAny (w a) a;- - matchAny :: (SimpleWitness w) => w a -> Any w -> Maybe a;- matchAny wit (MkAny cwit ca) = do- {- MkEqualType <- matchWitness cwit wit;- return ca;- };-- -- | Any value with a witness to a parameter of its type.- ;- data AnyF w f = forall a. MkAnyF (w a) (f a);- - matchAnyF :: (SimpleWitness w) => w a -> AnyF w f -> Maybe (f a);- matchAnyF wit (MkAnyF cwit cfa) = do- {- MkEqualType <- matchWitness cwit wit;- return cfa;- };-- -- | Any value with a witness to a parameter of its type of kind @* -> *@.- ;- data AnyF1 w f = forall (a :: * -> *). MkAnyF1 (w a) (f a);-- -- | Any value with a witness to a parameter of its type of kind @* -> * -> *@.- ;- data AnyF2 w f = forall (a :: * -> * -> *). MkAnyF2 (w a) (f a);-- -- | Any witness.- ;- data AnyWitness w = forall a. MkAnyWitness (w a);- - matchAnyWitness :: (SimpleWitness w) => w a -> AnyWitness w -> Bool;- matchAnyWitness wit (MkAnyWitness cwit) = isJust (matchWitness cwit wit);-- instance (SimpleWitness w) => Eq (AnyWitness w) where- {- (==) (MkAnyWitness wa) = matchAnyWitness wa;- };-- -- | Any witness of a type of kind @* -> *@.- ;- data AnyWitness1 w = forall (a :: * -> *). MkAnyWitness1 (w a);-- -- | Any witness of a type of kind @* -> * -> *@.- ;- data AnyWitness2 w = forall (a :: * -> * -> *). MkAnyWitness2 (w a);-}
− Data/Witness/EqualType.hs
@@ -1,17 +0,0 @@-module Data.Witness.EqualType where-{- import Control.Category;-- -- | witness that type parameters @a@ and @b@ are the same type- ;- data EqualType a b where- {- MkEqualType :: EqualType t t;- };-- instance Category EqualType where- {- id = MkEqualType;- MkEqualType . MkEqualType = MkEqualType;- };-}
− Data/Witness/List.hs
@@ -1,86 +0,0 @@-module Data.Witness.List where-{- import Data.Witness.Nat;- import Data.Witness.Representative;- import Data.Witness.SimpleWitness;- import Data.Witness.EqualType;- import Control.Category;- import Prelude hiding (id,(.));-- -- | a witness type for HList-style lists. Here we use @()@ and @(,)@ for @HNil@ and @HCons@. - -- The @w@ parameter is the witness type of the elements.- ;- data ListType w a where- {- NilListType :: ListType w ();- ConsListType :: w a -> ListType w b -> ListType w (a,b);- };-- instance Eq1 w => Eq1 (ListType w) where- {- equals1 NilListType NilListType = True;- equals1 (ConsListType pe pl) (ConsListType qe ql) = (equals1 pe qe) && (equals1 pl ql);- equals1 _ _ = False;- };-- instance Eq1 w => Eq (ListType w a) where- {- (==) = equals1;- };-- instance (Representative w) => Representative (ListType w) where- {- getRepWitness NilListType = MkRepWitness;- getRepWitness (ConsListType w lw) = case (getRepWitness w,getRepWitness lw) of- {- (MkRepWitness,MkRepWitness) -> MkRepWitness;- };- };-- instance (Representative w) => Is (ListType w) () where- {- representative = NilListType;- };-- instance (Is w a,Is (ListType w) b) => Is (ListType w) (a,b) where- {- representative = ConsListType representative representative;- };-- instance (SimpleWitness w) => SimpleWitness (ListType w) where- {- matchWitness NilListType NilListType = Just id;- matchWitness (ConsListType wpa wpb) (ConsListType wqa wqb) = do- {- MkEqualType <- matchWitness wpa wqa;- MkEqualType <- matchWitness wpb wqb;- return MkEqualType;- };- matchWitness _ _ = Nothing;- };--- class HasListElement n list where- {- type ListElement n list :: *;- getListElement :: Nat n -> list -> ListElement n list;- putListElement :: Nat n -> ListElement n list -> list -> list;- };-- modifyListElement :: (HasListElement n t) => Nat n -> (ListElement n t -> ListElement n t) -> t -> t;- modifyListElement n aa t = putListElement n (aa (getListElement n t)) t;-- instance HasListElement Zero (a,r) where- {- type ListElement Zero (a,r) = a;- getListElement _ (a,_) = a;- putListElement _ a (_,r) = (a,r);- };-- instance (HasListElement n r) => HasListElement (Succ n) (a,r) where- {- type ListElement (Succ n) (a,r) = ListElement n r;- getListElement (SuccNat n) (_,r) = getListElement n r;- putListElement (SuccNat n) a (f,r) = (f,putListElement n a r);- };-}
− Data/Witness/Nat.hs
@@ -1,53 +0,0 @@-module Data.Witness.Nat where-{- import Data.Witness.Representative;- import Data.Witness.SimpleWitness;- import Data.Witness.EqualType;- import Data.Maybe;- import Prelude hiding (id,(.));-- data Zero;- - data Succ n;- - data Nat t where- {- ZeroNat :: Nat Zero;- SuccNat :: Nat t -> Nat (Succ t);- };-- instance SimpleWitness Nat where- {- matchWitness ZeroNat ZeroNat = return MkEqualType;- matchWitness (SuccNat a) (SuccNat b) = do- {- MkEqualType <- matchWitness a b;- return MkEqualType;- };- matchWitness _ _ = Nothing;- };-- instance Eq1 Nat where- {- equals1 a b = isJust (matchWitness a b);- };-- instance Representative Nat where- {- getRepWitness ZeroNat = MkRepWitness;- getRepWitness (SuccNat n) = case getRepWitness n of- {- MkRepWitness -> MkRepWitness;- };- };-- instance Is Nat Zero where- {- representative = ZeroNat;- };-- instance (Is Nat n) => Is Nat (Succ n) where- {- representative = SuccNat representative;- };-}
− Data/Witness/Representative.hs
@@ -1,72 +0,0 @@-module Data.Witness.Representative where-{- import Data.Witness.Any;- import Data.Witness.SimpleWitness;-- class Eq1 p where- {- equals1 :: forall a. p a -> p a -> Bool;- };-- data RepWitness rep a where- {- MkRepWitness :: (Is rep a) => RepWitness rep a;- };-- isWitnessRepresentative :: RepWitness rep a -> rep a;- isWitnessRepresentative MkRepWitness = representative;-- instance (SimpleWitness w) => SimpleWitness (RepWitness w) where- {- matchWitness wa wb = matchWitness (isWitnessRepresentative wa) (isWitnessRepresentative wb);- };-- class Eq1 rep => Representative rep where- {- -- | Every value is an instance of 'Is'.- ;- getRepWitness :: rep a -> RepWitness rep a;- };-- withRepresentative :: forall rep r. (Representative rep) => (forall a. (Is rep a) => rep a -> r) -> (forall b. rep b -> r);- withRepresentative foo rep = case getRepWitness rep of- {- MkRepWitness -> foo rep;- };-- -- | If two representatives have the same type, then they have the same value.- ;- class Representative rep => Is rep a where- {- -- | The representative value for type @a@.- ;- representative :: rep a;- };-- getRepresentative :: (Is rep a) => a -> rep a;- getRepresentative _ = representative;-- rerepresentative :: (Is rep a) => p a -> rep a;- rerepresentative _ = representative;-- mkAny :: (Is rep a) => a -> Any rep;- mkAny a = MkAny representative a;-- mkAnyF :: (Is rep a) => f a -> AnyF rep f;- mkAnyF fa = MkAnyF representative fa;-- instance Eq1 (RepWitness rep) where- {- equals1 MkRepWitness MkRepWitness = True;- };-- instance Representative (RepWitness rep) where- {- getRepWitness MkRepWitness = MkRepWitness;- };-- instance (Is rep a) => Is (RepWitness rep) a where- {- representative = MkRepWitness;- };-}
− Data/Witness/SimpleWitness.hs
@@ -1,15 +0,0 @@-module Data.Witness.SimpleWitness where-{- import Data.Witness.EqualType;-- -- | @w@ is a simple witness type if each value witnesses to a single type. Thus if two values are the same, then they have the same type.- ;- class SimpleWitness w where- {- -- | If the two values are the same, then @a@ and @b@ are the same type.- --- -- As an equivalence relation, 'matchWitness' must be reflexive, commutative, and transitive.- ;- matchWitness :: w a -> w b -> Maybe (EqualType a b);- };-}
− Data/Witness/Type.hs
@@ -1,28 +0,0 @@-module Data.Witness.Type where-{- import Data.Witness.Representative;-- -- | The simplest 'Representative', with one value that represents all types.- ;- data Type a = Type;-- instance Eq1 Type where- {- equals1 Type Type = True;- };-- instance Eq (Type a) where- {- (==) = equals1;- };-- instance Representative Type where- {- getRepWitness Type = MkRepWitness;- };-- instance Is Type a where- {- representative = Type;- };-}
− Data/Witness/WitnessDict.hs
@@ -1,63 +0,0 @@-module Data.Witness.WitnessDict where-{- import Data.Witness.Any;- import Data.Witness.SimpleWitness;- import Data.Maybe;- - -- | A dictionary that is heterogenous up to its simple witness type @w@. - -- Witnesses are the keys of the dictionary, and the values they witness are the values of the dictionary.- ;- newtype WitnessDict w = MkWitnessDict [Any w];- - -- | An empty dictionary.- ;- emptyWitnessDict :: WitnessDict w;- emptyWitnessDict = MkWitnessDict[];- - -- | Look up the first value in the dictionary that matches the given witness.- ;- witnessDictLookup :: (SimpleWitness w) => w a -> WitnessDict w -> Maybe a;- witnessDictLookup wit (MkWitnessDict cells) = listToMaybe (mapMaybe (matchAny wit) cells);- - -- | Modify the first value in the dictionary that matches a particular witness.- ;- witnessDictModify :: (SimpleWitness w) => w a -> (a -> a) -> WitnessDict w -> WitnessDict w;- witnessDictModify wit amap (MkWitnessDict cells) = MkWitnessDict - (replaceFirst ((fmap ((MkAny wit) . amap)) . (matchAny wit)) cells) where- {- replaceFirst :: (a -> Maybe a) -> [a] -> [a];- replaceFirst ama (a:aa) = case ama a of- {- Just newa -> (newa:aa);- _ -> a : (replaceFirst ama aa);- };- replaceFirst _ _ = [];- };-- -- | Replace the first value in the dictionary that matches the witness- ;- witnessDictReplace :: (SimpleWitness w) => w a -> a -> WitnessDict w -> WitnessDict w;- witnessDictReplace wit newa = witnessDictModify wit (const newa);- - -- | Add a witness and value as the first entry in the dictionary.- ;- witnessDictAdd :: w a -> a -> WitnessDict w -> WitnessDict w;- witnessDictAdd wit a (MkWitnessDict cells) = MkWitnessDict ((MkAny wit a):cells);- - -- | Remove the first entry in the dictionary that matches the given witness.- ;- witnessDictRemove :: (SimpleWitness w) => w a -> WitnessDict w -> WitnessDict w;- witnessDictRemove wit (MkWitnessDict cells) = MkWitnessDict - (removeFirst (\(MkAny cwit _) -> isJust (matchWitness wit cwit)) cells) where- {- removeFirst :: (a -> Bool) -> [a] -> [a];- removeFirst p (a:as) | p a = as;- removeFirst p (a:as) = a : (removeFirst p as);- removeFirst _ _ = [];- };- - -- | Create a dictionary from a list of witness\/value pairs- ;- witnessDictFromList :: (SimpleWitness w) => [Any w] -> WitnessDict w;- witnessDictFromList = MkWitnessDict;-}
− Data/Witness/WitnessFDict.hs
@@ -1,63 +0,0 @@-module Data.Witness.WitnessFDict where-{- import Data.Witness.Any;- import Data.Witness.SimpleWitness;- import Data.Maybe;- - -- | A dictionary that is heterogenous up to its simple witness type @w@. - -- Witnesses are the keys of the dictionary, and the values they witness are the values of the dictionary.- ;- newtype WitnessFDict w f = MkWitnessFDict [AnyF w f];- - -- | An empty dictionary.- ;- emptyWitnessFDict :: WitnessFDict w f;- emptyWitnessFDict = MkWitnessFDict [];- - -- | Look up the first value in the dictionary that matches the given witness.- ;- witnessFDictLookup :: (SimpleWitness w) => w a -> WitnessFDict w f -> Maybe (f a);- witnessFDictLookup wit (MkWitnessFDict cells) = listToMaybe (mapMaybe (matchAnyF wit) cells);- - -- | Modify the first value in the dictionary that matches a particular witness.- ;- witnessFDictModify :: (SimpleWitness w) => w a -> (f a -> f a) -> WitnessFDict w f -> WitnessFDict w f;- witnessFDictModify wit amap (MkWitnessFDict cells) = MkWitnessFDict - (replaceFirst ((fmap ((MkAnyF wit) . amap)) . (matchAnyF wit)) cells) where- {- replaceFirst :: (a -> Maybe a) -> [a] -> [a];- replaceFirst ama (a:aa) = case ama a of- {- Just newa -> (newa:aa);- _ -> a : (replaceFirst ama aa);- };- replaceFirst _ _ = [];- };-- -- | Replace the first value in the dictionary that matches the witness- ;- witnessFDictReplace :: (SimpleWitness w) => w a -> f a -> WitnessFDict w f -> WitnessFDict w f;- witnessFDictReplace wit newfa = witnessFDictModify wit (const newfa);- - -- | Add a witness and value as the first entry in the dictionary.- ;- witnessFDictAdd :: w a -> f a -> WitnessFDict w f -> WitnessFDict w f;- witnessFDictAdd wit fa (MkWitnessFDict cells) = MkWitnessFDict ((MkAnyF wit fa):cells);- - -- | Remove the first entry in the dictionary that matches the given witness.- ;- witnessFDictRemove :: (SimpleWitness w) => w a -> WitnessFDict w f -> WitnessFDict w f;- witnessFDictRemove wit (MkWitnessFDict cells) = MkWitnessFDict - (removeFirst (\(MkAnyF cwit _) -> isJust (matchWitness wit cwit)) cells) where- {- removeFirst :: (a -> Bool) -> [a] -> [a];- removeFirst p (a:as) | p a = as;- removeFirst p (a:as) = a : (removeFirst p as);- removeFirst _ _ = [];- };- - -- | Create a dictionary from a list of witness\/value pairs- ;- witnessFDictFromList :: (SimpleWitness w) => [AnyF w f] -> WitnessFDict w f;- witnessFDictFromList = MkWitnessFDict;-}
+ src/Data/Witness.hs view
@@ -0,0 +1,33 @@+module Data.Witness+(+ module Data.Proxy,+ module Data.Type.Equality,+ module Data.Witness.Any,+ module Data.Witness.WitnessDict,+ module Data.Witness.WitnessFDict,+ module Data.Witness.Nat,+ module Data.Witness.ListElement,+ module Data.Witness.List,+ module Data.Witness.Representative,+ module Data.Witness+) where+{+ import Data.Proxy;+ import Data.Type.Equality;+ import Data.Witness.Any;+ import Data.Witness.WitnessDict;+ import Data.Witness.WitnessFDict;+ import Data.Witness.Nat;+ import Data.Witness.ListElement;+ import Data.Witness.List;+ import Data.Witness.Representative;++ -- | See whether two represented and witnessed types are the same.+ ;+ matchIs :: forall w a b. (TestEquality w,Is w a,Is w b) => Proxy w -> Maybe (a :~: b);+ matchIs _ = testEquality r r where+ {+ r :: forall t. (Is w t) => w t;+ r = representative;+ };+}
+ src/Data/Witness/Any.hs view
@@ -0,0 +1,39 @@+module Data.Witness.Any where+{+ import Data.Maybe;+ import Data.Type.Equality;++ -- | Any value with a witness to it.+ ;+ data Any (w :: * -> *) = forall (a :: *). MkAny (w a) a;++ matchAny :: (TestEquality w) => w a -> Any w -> Maybe a;+ matchAny wit (MkAny cwit ca) = do+ {+ Refl <- testEquality cwit wit;+ return ca;+ };++ -- | Any value with a witness to a parameter of its type.+ ;+ data AnyF (w :: k -> *) (f :: k -> *) = forall (a :: k). MkAnyF (w a) (f a);++ matchAnyF :: (TestEquality w) => w a -> AnyF w f -> Maybe (f a);+ matchAnyF wit (MkAnyF cwit cfa) = do+ {+ Refl <- testEquality cwit wit;+ return cfa;+ };++ -- | Any witness.+ ;+ data AnyWitness (w :: k -> *) = forall (a :: k). MkAnyWitness (w a);++ matchAnyWitness :: (TestEquality w) => w a -> AnyWitness w -> Bool;+ matchAnyWitness wit (MkAnyWitness cwit) = isJust (testEquality cwit wit);++ instance (TestEquality w) => Eq (AnyWitness w) where+ {+ (==) (MkAnyWitness wa) = matchAnyWitness wa;+ };+}
+ src/Data/Witness/List.hs view
@@ -0,0 +1,358 @@+module Data.Witness.List where+{+ import Prelude hiding (id,(.));+ import Data.Witness.Representative;+ import Data.Type.Equality;+ import Control.Category.Dual;+ import Data.Constraint(Dict(..));+ import Control.Applicative;+ import Control.Category;+ import Data.Functor.Identity as Import;++ -- | a witness type for HList-style lists.+ -- The @w@ parameter is the witness type of the elements.+ ;+ data ListType (w :: * -> *) (lt :: *) where+ {+ NilListType :: ListType w ();+ ConsListType :: w a -> ListType w lt -> ListType w (a,lt);+ };++ instance Eq1 w => Eq1 (ListType w) where+ {+ equals1 NilListType NilListType = True;+ equals1 (ConsListType pe pl) (ConsListType qe ql) = (equals1 pe qe) && (equals1 pl ql);+ equals1 _ _ = False;+ };++ instance Eq1 w => Eq (ListType w a) where+ {+ (==) = equals1;+ };++ instance (Representative w) => Representative (ListType w) where+ {+ getRepWitness NilListType = Dict;+ getRepWitness (ConsListType w lw) = case (getRepWitness w,getRepWitness lw) of+ {+ (Dict,Dict) -> Dict;+ };+ };++ instance (Representative w) => Is (ListType w) () where+ {+ representative = NilListType;+ };++ instance (Is w a,Is (ListType w) lt) => Is (ListType w) (a,lt) where+ {+ representative = ConsListType representative representative;+ };++ instance (TestEquality w) => TestEquality (ListType w) where+ {+ testEquality NilListType NilListType = Just Refl;+ testEquality (ConsListType wpa wpb) (ConsListType wqa wqb) = do+ {+ Refl <- testEquality wpa wqa;+ Refl <- testEquality wpb wqb;+ return Refl;+ };+ testEquality _ _ = Nothing;+ };++ listFill :: ListType w t -> (forall a. w a -> a) -> t;+ listFill NilListType _f = ();+ listFill (ConsListType wa wr) f = (f wa,listFill wr f);++ listMap :: ListType w t -> (forall a. w a -> a -> a) -> t -> t;+ listMap NilListType _f () = ();+ listMap (ConsListType wa wr) f (a,rest) = (f wa a,listMap wr f rest);++ listLift2 :: ListType w t -> (forall a. w a -> a -> a -> a) -> t -> t -> t;+ listLift2 NilListType _f () () = ();+ listLift2 (ConsListType wa wr) f (a,resta) (b,restb) = (f wa a b,listLift2 wr f resta restb);++ listTypeToList :: (forall a. w a -> r) -> ListType w t -> [r];+ listTypeToList _wr NilListType = [];+ listTypeToList wr (ConsListType wa rest) = (wr wa):(listTypeToList wr rest);++ listTypeMap :: (forall a. w1 a -> w2 a) -> ListType w1 t -> ListType w2 t;+ listTypeMap _ww NilListType = NilListType;+ listTypeMap ww (ConsListType wa rest) = ConsListType (ww wa) (listTypeMap ww rest);++ listIdentity :: ListType Identity lt -> lt;+ listIdentity NilListType = ();+ listIdentity (ConsListType (Identity a) rest) = (a,listIdentity rest);++ listSequence :: (Applicative f) => ListType f lt -> f lt;+ listSequence NilListType = pure ();+ listSequence (ConsListType fa rest) = liftA2 (,) fa (listSequence rest);++ data AppendList w la lb = forall lr. MkAppendList+ {+ listAppendWitness :: ListType w lr,+ listAppend :: la -> lb -> lr,+ listSplit :: lr -> (la,lb)+ };++ appendList :: ListType w la -> ListType w lb -> AppendList w la lb;+ appendList NilListType wlb = MkAppendList+ {+ listAppendWitness = wlb,+ listAppend = \() lb -> lb,+ listSplit = \lb -> ((),lb)+ };+ appendList (ConsListType wa wla) wlb = case appendList wla wlb of+ {+ MkAppendList wit join split -> MkAppendList+ {+ listAppendWitness = ConsListType wa wit,+ listAppend = \(a,la) lb -> (a,join la lb),+ listSplit = \(a,lab) -> case split lab of+ {+ (la,lb) -> ((a,la),lb);+ }+ };+ };++ data AddItemList w a l = forall lr. MkAddItemList+ {+ listAddItemWitness :: ListType w lr,+ listAddItem :: a -> l -> lr,+ listSplitItem :: lr -> (a,l)+ };++ addListItem :: w a -> ListType w l -> AddItemList w a l;+ addListItem wa wl = MkAddItemList+ {+ listAddItemWitness = ConsListType wa wl,+ listAddItem = (,),+ listSplitItem = id+ };++ data MergeItemList w a l = forall lr. MkMergeItemList+ {+ listMergeItemWitness :: ListType w lr,+ listMergeItem :: (Maybe a -> a) -> l -> lr,+ listUnmergeItem :: lr -> (a,l)+ };++ mergeListItem :: (TestEquality w) => ListType w l -> w a -> MergeItemList w a l;+ mergeListItem NilListType wa = MkMergeItemList+ {+ listMergeItemWitness = ConsListType wa NilListType,+ listMergeItem = \maa () -> (maa Nothing,()),+ listUnmergeItem = id+ };+ mergeListItem wl@(ConsListType wa' _) wa | Just Refl <- testEquality wa wa' = MkMergeItemList+ {+ listMergeItemWitness = wl,+ listMergeItem = \maa (a,l) -> (maa (Just a),l),+ listUnmergeItem = \(a,l) -> (a,(a,l))+ };+ mergeListItem (ConsListType wa' wl) wa = case mergeListItem wl wa of+ {+ MkMergeItemList wit merge unmerge -> MkMergeItemList+ {+ listMergeItemWitness = ConsListType wa' wit,+ listMergeItem = \maa (a',l) -> (a',merge maa l),+ listUnmergeItem = \(a',l') -> case unmerge l' of+ {+ (a,l) -> (a,(a',l));+ }+ };+ };++ data MergeList w la lb = forall lr. MkMergeList+ {+ listMergeWitness :: ListType w lr,+ listMerge :: (forall t. w t -> t -> t -> t) -> la -> lb -> lr,+ listUnmerge :: lr -> (la,lb)+ };++ mergeList :: (TestEquality w) => ListType w la -> ListType w lb -> MergeList w la lb;+ mergeList wla NilListType = MkMergeList+ {+ listMergeWitness = wla,+ listMerge = \_ la () -> la,+ listUnmerge = \la -> (la,())+ };+ mergeList wla (ConsListType wb wlb) = case mergeListItem wla wb of+ {+ MkMergeItemList wla' mergeItem unmergeItem -> case mergeList wla' wlb of+ {+ MkMergeList wlr merge unmerge -> MkMergeList+ {+ listMergeWitness = wlr,+ listMerge = \f la (b,lb) -> merge f (mergeItem (\mb' -> case mb' of+ {+ Just b' -> f wb b' b;+ Nothing -> b;+ }) la) lb,+ listUnmerge = \lr -> case unmerge lr of+ {+ (la',lb) -> case unmergeItem la' of+ {+ (b,la) -> (la,(b,lb));+ };+ }+ };+ };+ };++ -- could use data-lens:Control.Category.Product(Tensor)+ class Tensor cc where+ {+ tensorUnit :: cc () ();+ tensorPair :: cc a1 b1 -> cc a2 b2 -> cc (a1,a2) (b1,b2);+ };++ instance Tensor (->) where+ {+ tensorUnit = id;+ tensorPair ab1 ab2 (a1,a2) = (ab1 a1,ab2 a2);+ };++ instance (Tensor cc) => Tensor (Dual cc) where+ {+ tensorUnit = Dual tensorUnit;+ tensorPair (Dual ab1) (Dual ab2) = Dual (tensorPair ab1 ab2);+ };++ type MapWitness cc w1 w2 = forall r v1. w1 v1 -> (forall v2. w2 v2 -> (cc v1 v2) -> r) -> r;++ sameMapWitness :: (forall v. w v -> cc v v) -> MapWitness cc w w;+ sameMapWitness wc w wcr = wcr w (wc w);++ data MapList cc w2 l = forall lr. MkMapList+ {+ listMapWitness :: ListType w2 lr,+ listMapW :: cc l lr+ };++ mapList :: (Tensor cc) => MapWitness cc w1 w2 -> ListType w1 l -> MapList cc w2 l;+ mapList _ NilListType = MkMapList+ {+ listMapWitness = NilListType,+ listMapW = tensorUnit+ };+ mapList mapwit (ConsListType w rest) = case mapList mapwit rest of+ {+ MkMapList wit listMapW' -> mapwit w (\w' vmap -> MkMapList+ {+ listMapWitness = ConsListType w' wit,+ listMapW = tensorPair vmap listMapW'+ });+ };++ data RemoveFromList w a l = forall lr. MkRemoveFromList+ {+ listRemoveWitness :: ListType w lr,+ listInsert :: a -> lr -> l,+ listRemove :: l -> lr+ };++ removeAllMatching :: (TestEquality w) => w a -> ListType w l -> RemoveFromList w a l;+ removeAllMatching _ NilListType = MkRemoveFromList+ {+ listRemoveWitness = NilListType,+ listInsert = \_ -> id,+ listRemove = id+ };+ removeAllMatching wa (ConsListType wb rest) = case removeAllMatching wa rest of+ {+ MkRemoveFromList wit ins rm -> case testEquality wa wb of+ {+ Just Refl -> MkRemoveFromList+ {+ listRemoveWitness = wit,+ listInsert = \a l2 -> (a,ins a l2),+ listRemove = \(_,l1) -> rm l1+ };+ Nothing -> MkRemoveFromList+ {+ listRemoveWitness = ConsListType wb wit,+ listInsert = \a (b,l2) -> (b,ins a l2),+ listRemove = \(b,l1) -> (b,rm l1)+ };+ };+ };++ data RemoveManyFromList wit lx l = forall lr. MkRemoveManyFromList+ {+ listRemoveManyWitness :: ListType wit lr,+ listInsertMany :: lx -> lr -> l,+ listRemoveMany :: l -> lr+ };++ removeAllMatchingMany :: (TestEquality wit) => ListType wit lx -> ListType wit l -> RemoveManyFromList wit lx l;+ removeAllMatchingMany NilListType wl = MkRemoveManyFromList+ {+ listRemoveManyWitness = wl,+ listInsertMany = \_ lr -> lr,+ listRemoveMany = \l -> l+ };+ removeAllMatchingMany (ConsListType wa wlx) wl = case removeAllMatching wa wl of+ {+ MkRemoveFromList wl' ins rm -> case removeAllMatchingMany wlx wl' of+ {+ MkRemoveManyFromList wl'' insM remM -> MkRemoveManyFromList+ {+ listRemoveManyWitness = wl'',+ listInsertMany = \(a,lx) lr -> ins a (insM lx lr),+ listRemoveMany = remM . rm+ };+ };+ };++ newtype EitherWitness (w1 :: k -> *) (w2 :: k -> *) (a :: k) = MkEitherWitness (Either (w1 a) (w2 a));++ instance (TestEquality w1,TestEquality w2) => TestEquality (EitherWitness w1 w2) where+ {+ testEquality (MkEitherWitness (Left wa)) (MkEitherWitness (Left wb)) = testEquality wa wb;+ testEquality (MkEitherWitness (Right wa)) (MkEitherWitness (Right wb)) = testEquality wa wb;+ testEquality _ _ = Nothing;+ };++ data PartitionList wit1 wit2 l = forall l1 l2. MkPartitionList+ {+ listPartitionWitness1 :: ListType wit1 l1,+ listPartitionWitness2 :: ListType wit2 l2,+ listFromPartition :: l1 -> l2 -> l,+ listToPartition1 :: l -> l1,+ listToPartition2 :: l -> l2+ };++ partitionList :: ListType (EitherWitness w1 w2) l -> PartitionList w1 w2 l;+ partitionList NilListType = MkPartitionList+ {+ listPartitionWitness1 = NilListType,+ listPartitionWitness2 = NilListType,+ listFromPartition = \() () -> (),+ listToPartition1 = \() -> (),+ listToPartition2 = \() -> ()+ };+ partitionList (ConsListType (MkEitherWitness (Left w1a)) rest) = case partitionList rest of+ {+ MkPartitionList pw1 pw2 fp tp1 tp2 -> MkPartitionList+ {+ listPartitionWitness1 = ConsListType w1a pw1,+ listPartitionWitness2 = pw2,+ listFromPartition = \(a,l1) l2 -> (a,fp l1 l2),+ listToPartition1 = \(a,l) -> (a,tp1 l),+ listToPartition2 = \(_,l) -> tp2 l+ };+ };+ partitionList (ConsListType (MkEitherWitness (Right w2a)) rest) = case partitionList rest of+ {+ MkPartitionList pw1 pw2 fp tp1 tp2 -> MkPartitionList+ {+ listPartitionWitness1 = pw1,+ listPartitionWitness2 = ConsListType w2a pw2,+ listFromPartition = \l1 (a,l2) -> (a,fp l1 l2),+ listToPartition1 = \(_,l) -> tp1 l,+ listToPartition2 = \(a,l) -> (a,tp2 l)+ };+ };+}
+ src/Data/Witness/ListElement.hs view
@@ -0,0 +1,28 @@+module Data.Witness.ListElement where+{+ import Data.Witness.Nat;++ class HasListElement (n :: NatKind) (list :: *) where+ {+ type ListElement n list :: *;+ getListElement :: Nat n -> list -> ListElement n list;+ putListElement :: Nat n -> ListElement n list -> list -> list;+ };++ modifyListElement :: (HasListElement n t) => Nat n -> (ListElement n t -> ListElement n t) -> t -> t;+ modifyListElement n aa t = putListElement n (aa (getListElement n t)) t;++ instance HasListElement Zero (a,r) where+ {+ type ListElement Zero (a,r) = a;+ getListElement _ (a,_) = a;+ putListElement _ a (_,r) = (a,r);+ };++ instance (HasListElement n r) => HasListElement (Succ n) (a,r) where+ {+ type ListElement (Succ n) (a,r) = ListElement n r;+ getListElement (SuccNat n) (_,r) = getListElement n r;+ putListElement (SuccNat n) a (f,r) = (f,putListElement n a r);+ };+}
+ src/Data/Witness/Nat.hs view
@@ -0,0 +1,51 @@+module Data.Witness.Nat where+{+ import Prelude hiding (id,(.));+ import Data.Maybe;+ import Data.Type.Equality;+ import Data.Constraint(Dict(..));+ import Data.Witness.Representative;++ data NatKind = Zero | Succ NatKind;++ data Nat (t :: NatKind) where+ {+ ZeroNat :: Nat Zero;+ SuccNat :: Nat t -> Nat (Succ t);+ };++ instance TestEquality Nat where+ {+ testEquality ZeroNat ZeroNat = return Refl;+ testEquality (SuccNat a) (SuccNat b) = do+ {+ Refl <- testEquality a b;+ return Refl;+ };+ testEquality _ _ = Nothing;+ };++ instance Eq1 Nat where+ {+ equals1 a b = isJust (testEquality a b);+ };++ instance Representative Nat where+ {+ getRepWitness ZeroNat = Dict;+ getRepWitness (SuccNat n) = case getRepWitness n of+ {+ Dict -> Dict;+ };+ };++ instance Is Nat Zero where+ {+ representative = ZeroNat;+ };++ instance (Is Nat n) => Is Nat (Succ n) where+ {+ representative = SuccNat representative;+ };+}
+ src/Data/Witness/Representative.hs view
@@ -0,0 +1,64 @@+module Data.Witness.Representative where+{+ import Data.Witness.Any;+ import Data.Constraint;+ import Data.Proxy;++ class Eq1 (p :: k -> *) where+ {+ equals1 :: forall a. p a -> p a -> Bool;+ };++ instance Eq1 Proxy where+ {+ equals1 Proxy Proxy = True;+ };++ isWitnessRepresentative :: Dict (Is rep a) -> rep a;+ isWitnessRepresentative Dict = representative;++ class Eq1 rep => Representative (rep :: k -> *) where+ {+ -- | Every value is an instance of 'Is'.+ ;+ getRepWitness :: forall (a :: k). rep a -> Dict (Is rep a);+ };++ instance Representative Proxy where+ {+ getRepWitness Proxy = Dict;+ };++ withRepresentative :: forall (rep :: k -> *) r. (Representative rep) =>+ (forall (a :: k). (Is rep a) => rep a -> r) -> (forall (b :: k). rep b -> r);+ withRepresentative foo rep = case getRepWitness rep of+ {+ Dict -> foo rep;+ };++ -- | If two representatives have the same type, then they have the same value.+ ;+ class Representative rep => Is (rep :: k -> *) (a :: k) where+ {+ -- | The representative value for type @a@.+ ;+ representative :: rep a;+ };++ instance Is Proxy a where+ {+ representative = Proxy;+ };++ getRepresentative :: (Is rep a) => a -> rep a;+ getRepresentative _ = representative;++ rerepresentative :: (Is rep a) => p a -> rep a;+ rerepresentative _ = representative;++ mkAny :: (Is rep a) => a -> Any rep;+ mkAny a = MkAny representative a;++ mkAnyF :: (Is rep a) => f a -> AnyF rep f;+ mkAnyF fa = MkAnyF representative fa;+}
+ src/Data/Witness/WitnessDict.hs view
@@ -0,0 +1,63 @@+module Data.Witness.WitnessDict where+{+ import Data.Maybe;+ import Data.Type.Equality;+ import Data.Witness.Any;++ -- | A dictionary that is heterogenous up to its simple witness type @w@.+ -- Witnesses are the keys of the dictionary, and the values they witness are the values of the dictionary.+ ;+ newtype WitnessDict (w :: * -> *) = MkWitnessDict [Any w];++ -- | An empty dictionary.+ ;+ emptyWitnessDict :: WitnessDict w;+ emptyWitnessDict = MkWitnessDict[];++ -- | Look up the first value in the dictionary that matches the given witness.+ ;+ witnessDictLookup :: (TestEquality w) => w a -> WitnessDict w -> Maybe a;+ witnessDictLookup wit (MkWitnessDict cells) = listToMaybe (mapMaybe (matchAny wit) cells);++ -- | Modify the first value in the dictionary that matches a particular witness.+ ;+ witnessDictModify :: (TestEquality w) => w a -> (a -> a) -> WitnessDict w -> WitnessDict w;+ witnessDictModify wit amap (MkWitnessDict cells) = MkWitnessDict+ (replaceFirst ((fmap ((MkAny wit) . amap)) . (matchAny wit)) cells) where+ {+ replaceFirst :: (a -> Maybe a) -> [a] -> [a];+ replaceFirst ama (a:aa) = case ama a of+ {+ Just newa -> (newa:aa);+ _ -> a : (replaceFirst ama aa);+ };+ replaceFirst _ _ = [];+ };++ -- | Replace the first value in the dictionary that matches the witness+ ;+ witnessDictReplace :: (TestEquality w) => w a -> a -> WitnessDict w -> WitnessDict w;+ witnessDictReplace wit newa = witnessDictModify wit (const newa);++ -- | Add a witness and value as the first entry in the dictionary.+ ;+ witnessDictAdd :: w a -> a -> WitnessDict w -> WitnessDict w;+ witnessDictAdd wit a (MkWitnessDict cells) = MkWitnessDict ((MkAny wit a):cells);++ -- | Remove the first entry in the dictionary that matches the given witness.+ ;+ witnessDictRemove :: (TestEquality w) => w a -> WitnessDict w -> WitnessDict w;+ witnessDictRemove wit (MkWitnessDict cells) = MkWitnessDict+ (removeFirst (\(MkAny cwit _) -> isJust (testEquality wit cwit)) cells) where+ {+ removeFirst :: (a -> Bool) -> [a] -> [a];+ removeFirst p (a:as) | p a = as;+ removeFirst p (a:as) = a : (removeFirst p as);+ removeFirst _ _ = [];+ };++ -- | Create a dictionary from a list of witness\/value pairs+ ;+ witnessDictFromList :: (TestEquality w) => [Any w] -> WitnessDict w;+ witnessDictFromList = MkWitnessDict;+}
+ src/Data/Witness/WitnessFDict.hs view
@@ -0,0 +1,63 @@+module Data.Witness.WitnessFDict where+{+ import Data.Maybe;+ import Data.Type.Equality;+ import Data.Witness.Any;++ -- | A dictionary that is heterogenous up to its simple witness type @w@.+ -- Witnesses are the keys of the dictionary, and the values they witness are the values of the dictionary.+ ;+ newtype WitnessFDict (w :: k -> *) (f :: k -> *) = MkWitnessFDict [AnyF w f];++ -- | An empty dictionary.+ ;+ emptyWitnessFDict :: WitnessFDict w f;+ emptyWitnessFDict = MkWitnessFDict [];++ -- | Look up the first value in the dictionary that matches the given witness.+ ;+ witnessFDictLookup :: (TestEquality w) => w a -> WitnessFDict w f -> Maybe (f a);+ witnessFDictLookup wit (MkWitnessFDict cells) = listToMaybe (mapMaybe (matchAnyF wit) cells);++ -- | Modify the first value in the dictionary that matches a particular witness.+ ;+ witnessFDictModify :: (TestEquality w) => w a -> (f a -> f a) -> WitnessFDict w f -> WitnessFDict w f;+ witnessFDictModify wit amap (MkWitnessFDict cells) = MkWitnessFDict+ (replaceFirst ((fmap ((MkAnyF wit) . amap)) . (matchAnyF wit)) cells) where+ {+ replaceFirst :: (a -> Maybe a) -> [a] -> [a];+ replaceFirst ama (a:aa) = case ama a of+ {+ Just newa -> (newa:aa);+ _ -> a : (replaceFirst ama aa);+ };+ replaceFirst _ _ = [];+ };++ -- | Replace the first value in the dictionary that matches the witness+ ;+ witnessFDictReplace :: (TestEquality w) => w a -> f a -> WitnessFDict w f -> WitnessFDict w f;+ witnessFDictReplace wit newfa = witnessFDictModify wit (const newfa);++ -- | Add a witness and value as the first entry in the dictionary.+ ;+ witnessFDictAdd :: w a -> f a -> WitnessFDict w f -> WitnessFDict w f;+ witnessFDictAdd wit fa (MkWitnessFDict cells) = MkWitnessFDict ((MkAnyF wit fa):cells);++ -- | Remove the first entry in the dictionary that matches the given witness.+ ;+ witnessFDictRemove :: (TestEquality w) => w a -> WitnessFDict w f -> WitnessFDict w f;+ witnessFDictRemove wit (MkWitnessFDict cells) = MkWitnessFDict+ (removeFirst (\(MkAnyF cwit _) -> isJust (testEquality wit cwit)) cells) where+ {+ removeFirst :: (a -> Bool) -> [a] -> [a];+ removeFirst p (a:as) | p a = as;+ removeFirst p (a:as) = a : (removeFirst p as);+ removeFirst _ _ = [];+ };++ -- | Create a dictionary from a list of witness\/value pairs+ ;+ witnessFDictFromList :: (TestEquality w) => [AnyF w f] -> WitnessFDict w f;+ witnessFDictFromList = MkWitnessFDict;+}
witness.cabal view
@@ -1,53 +1,52 @@-cabal-version: >= 1.6+cabal-version: >=1.14+name: witness+version: 0.3+x-follows-version-policy:+license: BSD3+license-file: LICENSE+copyright: Ashley Yakeley <ashley@semantic.org>+author: Ashley Yakeley <ashley@semantic.org>+maintainer: Ashley Yakeley <ashley@semantic.org>+homepage: https://github.com/AshleyYakeley/witness+bug-reports: https://github.com/AshleyYakeley/witness/issues+synopsis: values that witness types+description:+ A witness is a value that /witnesses/ some sort of constraint on some list of type variables.+ This library provides support for simple witnesses, that constrain a type variable to a single type, and equality witnesses, that constrain two type variables to be the same type.+ It also provides classes for representatives, which are values that represent types.+ See the paper /Witnesses and Open Witnesses/ (<http://semantic.org/stuff/Open-Witnesses.pdf>).+category: Data+build-type: Simple -name: witness-version: 0.2-build-type: Simple-license: BSD3-license-file: LICENSE-copyright:-maintainer: Ashley Yakeley <ashley@semantic.org>-build-depends: base == 4.*, mtl >=1.1-stability:-homepage:-package-url:-bug-reports:-synopsis: values that witness types-description: A witness is a value that /witnesses/ some sort of constraint on some list of type variables.- This library provides support for simple witnesses, that constrain a type variable to a single type, and equality witnesses, that constrain two type variables to be the same type. It also provides classes for representatives, which are values that represent types.- See the paper /Witnesses and Open Witnesses/ (<http://semantic.org/stuff/Open-Witnesses.pdf>).-category: Data-author: Ashley Yakeley <ashley@semantic.org>-tested-with:-data-files:-data-dir: ""-extra-source-files:-extra-tmp-files:-exposed-modules: Data.Witness Data.Witness.SimpleWitness- Data.Witness.Type Data.Witness.List Data.Witness.WitnessDict- Data.Witness.WitnessFDict Data.Witness.Any Data.Witness.Nat- Data.Witness.Representative Data.Witness.EqualType-exposed: True-buildable: True-build-tools:-cpp-options:-cc-options:-ld-options:-pkgconfig-depends:-frameworks:-c-sources:-extensions: MultiParamTypeClasses RankNTypes FlexibleContexts- FlexibleInstances EmptyDataDecls KindSignatures TypeFamilies GADTs-extra-libraries:-extra-lib-dirs:-includes:-install-includes:-include-dirs:-hs-source-dirs: .-other-modules:-ghc-prof-options:-ghc-shared-options:-ghc-options: -Wall-hugs-options:-nhc98-options:-jhc-options:+library+ hs-source-dirs: src+ default-language: Haskell98+ default-extensions:+ MultiParamTypeClasses+ RankNTypes+ FlexibleContexts+ TypeOperators+ FlexibleInstances+ EmptyDataDecls+ KindSignatures+ TypeFamilies+ GADTs+ PolyKinds+ DataKinds+ ScopedTypeVariables+ PatternGuards+ build-depends:+ base == 4.*,+ transformers >=0.3,+ categories == 1.0.*,+ constraints >= 0.3+ exposed-modules:+ Data.Witness.Any+ Data.Witness.WitnessDict+ Data.Witness.WitnessFDict+ Data.Witness.Nat+ Data.Witness.ListElement+ Data.Witness.List+ Data.Witness.Representative+ Data.Witness+ ghc-options: -Wall