git.iko.soy/type-level-sets
on master help sign in
6 files changed+92−31
since splitsnapshots
unifiedsplit
changelog.md+5 example2.hs+9 src/Data/Type/Map.hs+15−5 src/Data/Type/Set.hs+43−7 stack.yaml+1−1 type-level-sets.cabal+19−18
changelog.mdnew file+5
@@ -0,0 +1,5 @@
1+ # v0.8.9.0
2+
3+ - GHC 8.4 and 8.6 support.
4+ - Fixed bug in the delete operation.
5+ - Non-membership predicates
example2.hs+9
@@ -1,4 +1,5 @@
11{-# LANGUAGE DataKinds, TypeOperators, TypeFamilies, GADTs, StandaloneDeriving #-}
2+{-# LANGUAGE FlexibleContexts #-}
23
34import GHC.TypeLits
45import Data.Type.Set
@@ -19,3 +20,11 @@ bar = asSet $ Ext (S (S Z)) (Ext (S Z) (Ext (S Z) Empty))
1920
2021-- foobar :: Set '[Natural 0, Natural 1, Natural 2, Natural 3]
2122foobar = foo `union` bar
23+
24+nonMemberTest :: NonMember (Natural 0) as => Set as -> ()
25+nonMemberTest set = ()
26+
27+-- nonMemberTest meep is well typed
28+meep = asSet $ Ext (S Z) (Ext (S (S Z)) Empty)
29+-- nonMemberTest morp is ill typed
30+morp = asSet $ Ext (S Z) (Ext (S (S Z)) (Ext Z Empty))
src/Data/Type/Map.hs+15−5
@@ -84,7 +84,7 @@ class IsMember v t m where
8484instance {-# OVERLAPS #-} IsMember v t ((v ':-> t) ': m) where
8585 lookp _ (Ext _ x _) = x
8686
87−instance IsMember v t m => IsMember v t (x ': m) where
87+instance {-# OVERLAPPABLE #-} IsMember v t m => IsMember v t (x ': m) where
8888 lookp v (Ext _ _ m) = lookp v m
8989
9090
@@ -100,8 +100,12 @@ instance {-# OVERLAPS #-} Updatable v t ((v ':-> s) ': m) ((v ':-> t) ': m) wher
100100instance Updatable v t m n => Updatable v t ((w ':-> y) ': m) ((w ':-> y) ': n) where
101101 update (Ext w y m) v x = Ext w y (update m v x)
102102
103−instance Updatable v t '[] '[v ':-> t] where
104− update Empty v x = Ext v x Empty
103+-- instance Updatable v t '[] '[v ':-> t] where
104+-- update Empty v x = Ext v x Empty
105+
106+instance Updatable v t s ((v ':-> t) ': s) where
107+ update xs v x = Ext v x xs
108+
105109
106110{-| Predicate to check if in normalised map form -}
107111type IsMap s = (s ~ Nub (Sort s))
@@ -129,8 +133,14 @@ instance (KnownSymbol k, Show v, Show' (Map s)) => Show' (Map ((k :-> v) ': s))
129133instance Eq (Map '[]) where
130134 Empty == Empty = True
131135
132−instance (KnownSymbol k, Eq (Var k), Eq v, Eq (Map s)) => Eq (Map ((k :-> v) ': s)) where
133− (Ext k v m) == (Ext k' v' m') = k == k' && v == v' && m == m'
136+instance (Eq v, Eq (Map s)) => Eq (Map ((k :-> v) ': s)) where
137+ (Ext Var v m) == (Ext Var v' m') = v == v' && m == m'
138+
139+instance Ord (Map '[]) where
140+ compare Empty Empty = EQ
141+
142+instance (Ord v, Ord (Map s)) => Ord (Map ((k :-> v) ': s)) where
143+ compare (Ext Var v m) (Ext Var v' m') = compare v v' `mappend` compare m m'
134144
135145{-| Union of two finite maps (normalising) -}
136146union :: (Unionable s t) => Map s -> Map t -> Map (Union s t)
src/Data/Type/Set.hs+43−7
@@ -1,12 +1,13 @@
11{-# LANGUAGE GADTs, DataKinds, KindSignatures, TypeOperators, TypeFamilies,
22 MultiParamTypeClasses, FlexibleInstances, PolyKinds,
33 FlexibleContexts, UndecidableInstances, ConstraintKinds,
4− ScopedTypeVariables #-}
4+ ScopedTypeVariables, TypeInType #-}
55
66module Data.Type.Set (Set(..), Union, Unionable, union, quicksort, append,
77 Sort, Sortable, (:++), Split(..), Cmp, Filter, Flag(..),
88 Nub, Nubable(..), AsSet, asSet, IsSet, Subset(..),
9− Delete(..), Proxy(..)) where
9+ Delete(..), Proxy(..), remove, Remove, (:\),
10+ Member(..), NonMember, MemberP(..)) where
1011
1112import GHC.TypeLits
1213import Data.Type.Bool
@@ -15,7 +16,7 @@ import Data.Type.Equality
1516data Proxy (p :: k) = Proxy
1617
1718-- Value-level 'Set' representation, essentially a list
18−data Set (n :: [*]) where
19+data Set (n :: [k]) where
1920 {--| Construct an empty set -}
2021 Empty :: Set '[]
2122 {--| Extend a set with an element -}
@@ -73,6 +74,25 @@ append :: Set s -> Set t -> Set (s :++ t)
7374append Empty x = x
7475append (Ext e xs) ys = Ext e (append xs ys)
7576
77+{-| Delete elements from a set -}
78+type family (m :: [k]) :\ (x :: k) :: [k] where
79+ '[] :\ x = '[]
80+ (x ': xs) :\ x = xs :\ x
81+ (y ': xs) :\ x = y ': (xs :\ x)
82+
83+class Remove s t where
84+ remove :: Set s -> Proxy t -> Set (s :\ t)
85+
86+instance Remove '[] t where
87+ remove Empty Proxy = Empty
88+
89+instance {-# OVERLAPS #-} Remove xs x => Remove (x ': xs) x where
90+ remove (Ext _ xs) x@Proxy = remove xs x
91+
92+instance {-# OVERLAPPABLE #-} (((y : xs) :\ x) ~ (y : (xs :\ x)), Remove xs x)
93+ => Remove (y ': xs) x where
94+ remove (Ext y xs) (x@Proxy) = Ext y (remove xs x)
95+
7696{-| Splitting a union a set, given the sets we want to split it into -}
7797class Split s t st where
7898 -- where st ~ Union s t
@@ -93,8 +113,6 @@ instance {-# OVERLAPS #-} (Split s t st) => Split s (x ': t) (x ': st) where
93113 split (Ext x st) = let (s, t) = split st
94114 in (s, Ext x t)
95115
96−
97−
98116{-| Remove duplicates from a sorted list -}
99117type family Nub t where
100118 Nub '[] = '[]
@@ -130,10 +148,10 @@ class Subset s t where
130148instance Subset '[] '[] where
131149 subset xs = Empty
132150
133−instance Subset s t => Subset s (x ': t) where
151+instance {-# OVERLAPPABLE #-} Subset s t => Subset s (x ': t) where
134152 subset (Ext _ xs) = subset xs
135153
136−instance Subset s t => Subset (x ': s) (x ': t) where
154+instance {-# OVERLAPS #-} Subset s t => Subset (x ': s) (x ': t) where
137155 subset (Ext x xs) = Ext x (subset xs)
138156
139157
@@ -198,3 +216,21 @@ instance Conder False where
198216{-| Open-family for the ordering operation in the sort -}
199217
200218type family Cmp (a :: k) (b :: k) :: Ordering
219+
220+{-| Membership of an element in a set, with an acommanying
221+ value-level function that returns a bool -}
222+class Member a s where
223+ member :: Proxy a -> Set s -> Bool
224+
225+instance {-# OVERLAPS #-} Member a (a ': s) where
226+ member _ (Ext x _) = True
227+
228+instance {-# OVERLAPPABLE #-} Member a s => Member a (b ': s) where
229+ member a (Ext _ xs) = member a xs
230+
231+type family MemberP a s :: Bool where
232+ MemberP a '[] = False
233+ MemberP a (a ': s) = True
234+ MemberP a (b ': s) = MemberP a s
235+
236+type NonMember a s = MemberP a s ~ False
stack.yaml+1−1
@@ -1,7 +1,7 @@
11# For more information, see: https://github.com/commercialhaskell/stack/wiki/stack.yaml
22
33# Specifies the GHC version and set of packages available (e.g., lts-3.5, nightly-2015-09-21, ghc-7.10.2)
4−resolver: nightly-2016-07-18
4+resolver: lts-12.7
55
66# Local packages, usually specified by relative directory name
77packages:
type-level-sets.cabal+19−18
@@ -1,14 +1,14 @@
11name: type-level-sets
2−version: 0.8.0.0
2+version: 0.8.9.0
33synopsis: Type-level sets and finite maps (with value-level counterparts)
4−description:
4+description:
55 This package provides type-level sets (no duplicates, sorted to provide a normal form) via 'Set' and type-level
66 finite maps via 'Map', with value-level counterparts.
77 .
8− Described in the paper \"Embedding effect systems in Haskell\" by Dominic Orchard
9− and Tomas Petricek <http://www.cl.cam.ac.uk/~dao29/publ/haskell14-effects.pdf> (Haskell Symposium, 2014). This version now uses Quicksort to normalise the representation.
8+ Described in the paper \"Embedding effect systems in Haskell\" by Dominic Orchard
9+ and Tomas Petricek <http://www.cl.cam.ac.uk/~dao29/publ/haskell14-effects.pdf> (Haskell Symposium, 2014). This version now uses Quicksort to normalise the representation.
1010 .
11− Here is a brief example for finite maps:
11+ Here is a brief example for finite maps:
1212 .
1313 >
1414 > import Data.Type.Map
@@ -19,26 +19,26 @@ description:
1919 > combine x y = x + y
2020 >
2121 > foo :: Map '["x" :-> Int, "z" :-> Bool, "w" :-> Int]
22− > foo = Ext (Var :: (Var "x")) 2
23− > $ Ext (Var :: (Var "z")) True
24− > $ Ext (Var :: (Var "w")) 5
25− > $ Empty
22+ > foo = Ext (Var :: (Var "x")) 2
23+ > $ Ext (Var :: (Var "z")) True
24+ > $ Ext (Var :: (Var "w")) 5
25+ > $ Empty
2626 >
2727 > bar :: Map '["y" :-> Int, "w" :-> Int]
2828 > bar = Ext (Var :: (Var "y")) 3
2929 > $ Ext (Var :: (Var "w")) 1
3030 > $ Empty
31− >
31+ >
3232 > -- foobar :: Map '["w" :-> Int, "x" :-> Int, "y" :-> Int, "z" :-> Bool]
3333 > foobar = foo `union` bar
3434 .
3535 The 'Map' type for 'foobar' here shows the normalised form (sorted with no duplicates).
3636 The type signatures is commented out as it can be infered. Running the example we get:
3737 .
38− > >>> foobar
38+ > >>> foobar
3939 > {w :-> 6, x :-> 2, y :-> 3, z :-> True}
4040 .
41− Thus, we see that the values for \"w\" are added together.
41+ Thus, we see that the values for \"w\" are added together.
4242 For sets, here is an example:
4343 .
4444 > import GHC.TypeLits
@@ -48,7 +48,7 @@ description:
4848 > data Natural (a :: Nat) where
4949 > Z :: Natural 0
5050 > S :: Natural n -> Natural (n + 1)
51− >
51+ >
5252 > -- foo :: Set '[Natural 0, Natural 1, Natural 3]
5353 > foo = asSet $ Ext (S Z) (Ext (S (S (S Z))) (Ext Z Empty))
5454 >
@@ -63,15 +63,15 @@ description:
6363license: BSD3
6464license-file: LICENSE
6565category: Type System, Data Structures
66−copyright: 2013-16 University of Cambridge
66+copyright: 2013-18 University of Kent
6767author: Dominic Orchard
6868maintainer: Dominic Orchard
6969stability: experimental
7070build-type: Simple
7171cabal-version: >= 1.6
72−tested-with: GHC >= 8.0.1
72+tested-with: GHC >= 8.2.2
7373
74−extra-source-files: example.hs, example2.hs
74+extra-source-files: example.hs, example2.hs, changelog.md
7575
7676
7777source-repository head
@@ -80,10 +80,11 @@ source-repository head
8080
8181library
8282 hs-source-dirs: src
83+ other-extensions: TypeInType
8384
8485
8586 exposed-modules: Data.Type.Set
8687 Data.Type.Map
87−
88+
8889 build-depends: base < 5,
89− ghc-prim
90+ ghc-prim