git.iko.soy/type-level-sets
on 9139d17 help sign in
10 files changed+559−499
since splitsnapshots
unifiedsplit
README+21−42 TySet.hs+344 changelog.md−5 example-new.hs+86 example.hs+13−25 example2.hs−30 src/Data/Type/Map.hs−261 src/Data/Type/Set.hs+64−76 stack.yaml+1−1 type-level-sets.cabal+30−59
README+21−42
@@ -1,56 +1,35 @@
1−This library provides type-level sets and finite maps to Haskell, with a value level counterpart, and operations for taking the union, computing
2−subsets/submaps, and splitting sets/maps. This library was originally built based on
3−"Embedding effect systems in Haskell" (Dominic Orchard,
1+This library provides type-level sets to Haskell, with a value level counterpart, and operations for taking the union, computing
2+subsets, and split sets. Also included is a "mapping" type constructor that pairs symbols with types. This can be used to represent
3+sets of variable-type pairs, which is used in the paper "Embedding effect systems in Haskell" (Dominic Orchard,
44Tomas Petricek <http://www.cl.cam.ac.uk/~dao29/publ/haskell14-effects.pdf>) to embed effect sets.
55
66The following shows an example:
77
8− {-# LANGUAGE DataKinds, TypeOperators, TypeFamilies, MultiParamTypeClasses #-}
9− import Data.Type.Map
10−
11− -- Specifies how to combine duplicate key-value pairs for Int values
12− type instance Combine Int Int = Int
13− instance Combinable Int Int where
14− combine x y = x + y
15−
16− foo :: Map '["x" :-> Int, "z" :-> Bool, "w" :-> Int]
17− foo = Ext (Var :: (Var "x")) 2
18− $ Ext (Var :: (Var "z")) True
19− $ Ext (Var :: (Var "w")) 5
20− Empty
21−
22− bar :: Map '["y" :-> Int, "w" :-> Int]
23− bar = Ext (Var :: (Var "y")) 3
24− $ Ext (Var :: (Var "w")) 1
25− $ Empty
26−
27− -- foobar :: Map '["w" :-> Int, "x" :-> Int, "y" :-> Int, "z" :-> Bool]
28− foobar = foo `union` bar
29−
30−The 'Map' type for 'foobar' here shows the normalised form (sorted with no duplicates).
31−The type signatures is commented out as it can be infered. Running the example we get:
8+ {-# LANGUAGE DataKinds, TypeOperators #-}
329
33− *Main> foobar
34− {w :-> 6, x :-> 2, y :-> 3, z :-> True}
10+ import Data.Type.Set
3511
36−Thus, we see that values for 'w' are added.
12+ foo :: Set '["x" :-> Int, "z" :-> Int, "w" :-> Int]
13+ foo = Ext ((Var :: (Var "x")) :-> 2) $
14+ Ext ((Var :: (Var "z")) :-> 4) $
15+ Ext ((Var :: (Var "w")) :-> 5) $
16+ Empty
3717
38− import GHC.TypeLits
39− import Data.Type.Set
40− type instance Cmp (Natural n) (Natural m) = CmpNat n m
18+ bar :: Set '["y" :-> Int, "w" :-> Int]
19+ bar = Ext ((Var :: (Var "y")) :-> 3) $
20+ Ext ((Var :: (Var "w")) :-> 1) $
21+ Empty
4122
42− data Natural (a :: Nat) where
43− Z :: Natural 0
44− S :: Natural n -> Natural (n + 1)
23+ -- foobar :: Set '["w" :-> Int, "x" :-> Int, "y" :-> Int, "z" :-> Int]
24+ foobar = foo `union` bar
4525
46− -- foo :: Set '[Natural 0, Natural 1, Natural 3]
47− foo = asSet $ Ext (S Z) (Ext (S (S (S Z))) (Ext Z Empty))
26+The 'Set' type for 'foobar' here shows the normalised form (sorted with no duplicates).
27+The type signatures is commented out as it can be infered. Running the example we get:
4828
49− -- bar :: Set '[Natural 1, Natural 2]
50− bar = asSet $ Ext (S (S Z)) (Ext (S Z) (Ext (S Z) Empty))
29+ *Main> foobar
30+ {(Var :-> 1), (Var :-> 2), (Var :-> 3), (Var :-> 4)}
5131
52− -- foobar :: Set '[Natural 0, Natural 1, Natural 2, Natural 3]
53− foobar = foo `union` bar
32+Thus, we see that the first value paired with the "w" variable is dropped.
5433
5534
5635
TySet.hsnew file+344
@@ -0,0 +1,344 @@
1+-- {-# OPTIONS_GHC -package=ghc-7.10.1 #-}
2+{-# LANGUAGE TypeFamilies, DataKinds, PolyKinds, StandaloneDeriving, TypeOperators, FlexibleInstances, ScopedTypeVariables, ImplicitParams, MultiParamTypeClasses #-}
3+
4+module TySet(plugin, Set, Union, dropPrefix) where
5+
6+import TypeRep
7+import Type
8+import Kind
9+import TcEvidence
10+import CoAxiom
11+import Name
12+import OccName
13+import Var
14+import TyCon
15+import BasicTypes
16+
17+-- friends:
18+import Var
19+import VarEnv
20+import VarSet
21+import Name
22+import BasicTypes
23+import TyCon
24+import Class
25+import CoAxiom
26+
27+-- others
28+import PrelNames
29+import Outputable
30+import FastString
31+import Util
32+import DynFlags
33+
34+import TcPluginM ( TcPluginM, tcPluginIO, tcPluginTrace )
35+import TcRnMonad ( TcPlugin(..), TcPluginResult(..)
36+ , Ct(..), CtEvidence(..), CtLoc, ctLoc, ctPred
37+ , mkNonCanonical, isTouchableTcM, unsafeTcPluginTcM)
38+import Plugins ( CommandLineOption, defaultPlugin, Plugin(..) )
39+import GHC.TcPluginM.Extra
40+
41+import Debug.Trace
42+import Outputable
43+import DynFlags
44+
45+import Control.Monad
46+import Control.Monad.Trans.Maybe
47+import Control.Applicative
48+import qualified Data.Typeable as DT
49+import Data.List
50+
51+import Test.QuickCheck
52+import Test.QuickCheck.Property
53+
54+{- Set constructor -}
55+data Set (a :: [k])
56+{- Union operation -}
57+type family Union (a :: [k]) (b :: [k]) :: [k]
58+
59+type family Member (a :: k) (b :: [k]) :: Bool where
60+ Member x '[] = False
61+ Member x (x ': xs) = True
62+ Member x (y ': xs) = Member x xs
63+
64+{- Plugin setup -}
65+plugin :: Plugin
66+plugin = defaultPlugin { tcPlugin = Just . thePlugin }
67+
68+thePlugin :: [CommandLineOption] -> TcPlugin
69+thePlugin opts = TcPlugin
70+ { tcPluginInit = pluginInit opts
71+ , tcPluginSolve = pluginSolve
72+ , tcPluginStop = pluginStop
73+ }
74+
75+class Debug t m where
76+ debug :: (?ifDebug :: Bool) => t -> m ()
77+instance Debug SDoc TcPluginM where
78+ debug x = tcPluginTrace "TySet" x
79+instance Debug String IO where
80+ debug x = putStrLn x
81+
82+pluginInit :: [CommandLineOption] -> TcPluginM ()
83+pluginInit _ = return ()
84+
85+pluginSolve :: () -> [Ct] -> [Ct] -> [Ct] -> TcPluginM TcPluginResult
86+pluginSolve () given derived wanted =
87+ let ?ifDebug = True in
88+
89+ do
90+ tcPluginIO $ debug "Running TySet equality plugin"
91+ debug $ ppCts wanted
92+ -- debug $ ppr $ head $ wanted
93+
94+ --solved <- findEmptySetEquality wanted
95+ (solved, generated) <- findSetEquality wanted
96+ return $ TcPluginOk solved generated
97+
98+pluginStop :: () -> TcPluginM ()
99+pluginStop _ = return ()
100+
101+-- Pretty print constraints
102+ppCts [] = text "(empty)"
103+ppCts cs = vcat (map ppr cs)
104+
105+{- Some debugging Show instances to help me understand what is coming in and out of GHC -}
106+deriving instance Show TyLit
107+deriving instance Show Type
108+instance Show Var where
109+ show v = showSDocUnsafe $ ppr v
110+instance Show TyCon where
111+ show tycon = showSDocUnsafe $ ppr tycon
112+instance Show Ct where
113+ show ct = showSDocUnsafe $ ppr ct
114+
115+{-
116+-- Prediacate one whether a type is = Set '[]
117+isEmptySetType t = do (x, tcs) <- splitTyConApp_maybe t
118+ guard $ length tcs == 2
119+ guard $ getOccString (tyConName x) == "Set"
120+ case tcs of [TyVarTy k, TyConApp con [TyVarTy k']] ->
121+ do guard $ k == k'
122+ guard $ (getOccString . tyConName $ con) == "[]"
123+ _ -> Nothing
124+-}
125+
126+getNameStr = getOccString . tyConName
127+
128+liftTc :: Maybe a -> MaybeT TcPluginM a
129+liftTc = MaybeT . return
130+
131+liftMt :: TcPluginM a -> MaybeT TcPluginM a
132+liftMt x = MaybeT (fmap Just x)
133+
134+findSetEquality :: [Ct] -> TcPluginM ([(EvTerm, Ct)], [Ct])
135+findSetEquality [] = return ([], [])
136+findSetEquality (ct : xs) =
137+ do x <- runMaybeT $
138+ do (Nominal, t1, t2) <- liftTc $ getEqPredTys_maybe (ctPred ct)
139+ a <- liftTc $ listTypeToTerm t1
140+ b <- "sofar sogood" `trace` liftTc $ listTypeToTerm t2
141+ (show (t1, a, t2, b)) `trace`
142+ if (a == b) then
143+ "are equal" `trace` return $ Left (EvCoercion $ TcRefl Nominal t1, ct)
144+ else -- not equal, try to find an mgu and generate conditions on that
145+ let ?ctLoc = ctLoc ct in
146+ do unifiers <- "not equal" `trace` mgu a b
147+ case unifiers of
148+ Left unifiers -> ("L unifiers: \n" ++ show unifiers) `trace` return $ Right []
149+ Right (dataUnifiers, unsolvedExtra) -> ("data unifiers:" ++ (show $ dataUnifiers)) `trace` return $ Right $ (EvCoercion $ TcRefl Nominal t1, ct) : map (\c -> (EvCoercion $ TcRefl Nominal undefined, c)) dataUnifiers
150+
151+ (solved, generated) <- findSetEquality xs
152+ case x of
153+ Just y -> case y of
154+ Left (ev, ct) -> return $ ((ev, ct) : solved, generated)
155+ Right cts -> return $ (solved ++ cts, generated)
156+ Nothing -> return (solved, generated)
157+
158+listTypeToTerm :: Type -> Maybe (TermTree Type)
159+listTypeToTerm t = case (splitTyConApp_maybe t) of
160+ Just (tcon, args) ->
161+ case getNameStr tcon of
162+ "Union" -> do guard $ (length args) >= 3
163+ (_ : (t1 : (t2 : ts))) <- return args
164+ t1' <- listTypeToTerm t1
165+ t2' <- listTypeToTerm t2
166+ return $ Union t1' t2'
167+ -- this case is probably temporary [see SessionListE.hs]
168+ ":++" -> do guard $ (length args) >= 3
169+ (_ : (t1 : (t2 : ts))) <- return args
170+ t1' <- listTypeToTerm t1
171+ t2' <- listTypeToTerm t2
172+ return $ Union t1' t2'
173+ ":" -> do guard $ (length args >= 2)
174+ (t1 : (t2 : ts)) <- return args
175+ (kind, args) <- splitTyConApp_maybe $ t1
176+ ts' <- listTypeToTerm $ head ts -- possible bug here
177+ return $ Union (Data [t2]) ts'
178+ "[]" -> do guard $ (length args == 1)
179+ [t] <- return args
180+ (kind, args) <- splitTyConApp_maybe $ t
181+ return $ Empty
182+
183+ _ -> return $ Empty -- Data [t]
184+ _ -> case t of
185+ TyVarTy v -> return $ Var $ v
186+
187+-- Representation for solving equalities on terms comprising union, data, and variables
188+
189+data TermTree a = Union (TermTree a) (TermTree a) | Empty | Var Var | Data [a] deriving Show
190+
191+-- if the second argument is a prefix of the first argument, then return Just of the suffix, else Nothing
192+dropPrefix :: Eq a => [a] -> [a] -> Maybe [a]
193+dropPrefix [] xs = Just []
194+dropPrefix xs [] = Just xs
195+dropPrefix (x:xs) (y:ys) | x == y = dropPrefix xs ys
196+ | otherwise = Nothing
197+
198+mguDataVars :: [a] -> [Var] -> Maybe [(Var, TermTree a)]
199+mguDataVars suffix [] = Nothing -- No variables to unify with
200+mguDataVars suffix (v:vs) = Just $ [(v, Data suffix)] ++ map (\v' -> (v', Var v)) vs
201+
202+mgu :: (?ctLoc :: CtLoc) => TermTree Type -> TermTree Type -> MaybeT TcPluginM (Either [(Var, TermTree Type)] ([Ct], ([Type], [Type]))) -- last component should be some equalities
203+mgu t1 t2 = let (vs1, ds1) = normalisedRep t1
204+ (vs2, ds2) = normalisedRep t2
205+ in ("----> " ++ show (ds1, ds2)) `trace`
206+ (show $ dropPrefix ds1 ds2) `trace`
207+ case (dropPrefix ds1 ds2) of
208+ Nothing -> case (dropPrefix ds2 ds1) of
209+ Nothing -> "el zilcho primo" `trace` do x <- liftMt (zipMatch ds1 ds2)
210+ return $ Right x -- ([], ([], []))
211+ Just suffix_ds2 -> "suffix_ds2" `trace`
212+ do x <- liftTc $ mguDataVars suffix_ds2 vs1
213+ return $ Left x
214+ Just suffix_ds1 -> ("suffix_ds1 " ++ (show suffix_ds1))
215+ `trace`
216+ if (suffix_ds1 == []) then
217+ do x <- liftMt (zipMatch ds1 ds2)
218+ ("zipm: ds1 = " ++ (show ds1) ++ " ds2 = " ++ (show ds2) ++ ": " ++ (show x)) `trace` return $ Right x -- ([], ([], []))
219+ else
220+ do x <- liftTc $ mguDataVars suffix_ds1 vs2
221+ return $ Left x
222+
223+mkEqualities :: (?ctLoc :: CtLoc) => [(Type, Type)] -> TcPluginM [Ct]
224+mkEqualities xs = (mapM (\(x, y) -> mkCt x y) xs) -- >>= (return . concat)
225+
226+mkCt t t' = fmap mkNonCanonical (newDerived ?ctLoc (uncurry mkPrimEqPred (t,t')))
227+
228+mkEqualities' (AppTy t1 t2) (AppTy t1' t2') = do ct <- mkCt t1 t1'
229+ ct' <- mkCt t2 t2'
230+ return [ct, ct']
231+mkEqualities' (TyConApp con kt) (TyConApp con' kt') | con == con' = mapM (uncurry mkCt) (zip kt kt')
232+mkEqualities' (FunTy t1 t2) (FunTy t1' t2') = do ct <- mkCt t1 t1'
233+ ct' <- mkCt t2 t2'
234+ return [ct, ct']
235+mkEqualities' (ForAllTy v t) (ForAllTy v' t') | v == v' = do ct <- mkCt t t'
236+ return [ct]
237+mkEqualities' t t' = do ct <- mkCt t t'
238+ return [ct]
239+
240+
241+
242+
243+zipMatch :: (?ctLoc :: CtLoc) => [Type] -> [Type] -> TcPluginM ([Ct], ([Type], [Type]))
244+zipMatch xs ys = let (unifiers, restL, restR) = zipMatch' xs ys
245+ in do unifiers' <- mkEqualities unifiers
246+ return $ (unifiers', (restL, restR))
247+
248+zipMatch' :: [a] -> [a] -> ([(a, a)], [a], [a])
249+zipMatch' [] xs = ([], [], xs)
250+zipMatch' xs [] = ([], xs, [])
251+zipMatch' (x:xs) (y:ys) = let (zips, l, r) = zipMatch' xs ys
252+ in ((x, y) : zips, l, r)
253+
254+
255+
256+
257+
258+
259+subst :: TermTree a -> [(Var, TermTree a)] -> TermTree a
260+subst (Union s t) theta = Union (subst s theta) (subst t theta)
261+subst (Var a) theta = case (lookup a theta) of
262+ Just t -> t
263+ Nothing -> Var a
264+subst t theta = t
265+
266+instance Eq a => Eq (TermTree a) where
267+ t1 == t2 = let (vs1, ds1) = normalisedRep t1
268+ (vs2, ds2) = normalisedRep t2
269+ in ("vars = " ++ (show (vs1, vs2)) ++ " eq = " ++ (show (vs1 == vs2)))
270+ `trace` (vs1 == vs2) && (all (flip elem $ ds2) ds1) && (all (flip elem $ ds1) ds2)
271+
272+normalisedRep :: Eq a => TermTree a -> ([Var], [a])
273+normalisedRep t = let (vs, ds) = separate t
274+ in (nub . sort $ vs, nub ds)
275+
276+separate :: TermTree a -> ([Var], [a])
277+separate Empty = ([], [])
278+separate (Var s) = ([s], [])
279+separate (Data xs) = ([], xs)
280+separate (Union a b) = let (vs1, ds1) = separate a
281+ (vs2, ds2) = separate b
282+ in (vs1++vs2, ds1++ds2)
283+
284+{-- Unit testing of normaliser and set equality --}
285+testSetTermEquality :: IO ()
286+testSetTermEquality = quickCheck (\((n, m) :: (TermTree Int, TermTree Int)) -> n == m)
287+
288+mkVar :: String -> Var
289+mkVar = undefined
290+
291+instance Arbitrary (TermTree Int, TermTree Int) where
292+ arbitrary = sized $ \vars ->
293+ sized $ \datums ->
294+ do v0 <- (vector vars)::(Gen [String])
295+ v <- return $ map mkVar v0
296+ dat <- (vector datums)::(Gen [Int])
297+ v' <- shuffle v
298+ dat' <- shuffle dat
299+ g1 <- gen v dat
300+ g2 <- gen v' dat'
301+
302+ -- Soundness check on generated tree
303+ let (v0, dat0) = separate g1
304+ (v1, dat1) = separate g2
305+ norm :: (Ord a) => [a] -> [a]
306+ norm = nub . sort
307+
308+ if and [(norm v0) == (norm v), (norm v1) == (norm v),
309+ (norm dat) == (norm dat0), (norm dat) == (norm dat1)]
310+ then return ()
311+ else error $ "Generated trees failed soundness check: " ++ (show g1) ++ " " ++ (show g2)
312+ return (g1, g2)
313+
314+-- Arbitrarily permute a union of two generators
315+unionPerm x y = do x' <- x
316+ y' <- y
317+ elements [Union x' y', Union y' x']
318+
319+-- Generates arbitrary terms from a list of variables and list of Int adtums
320+gen :: [Var] -> [Int] -> Gen (TermTree Int)
321+gen [] [] = return $ Empty
322+gen vs ds = do -- Choose between 0 and 1 if 'vs' is empty, or 0-2 if 'vs' has elements
323+ choose <- suchThat arbitrary (\x -> x<=(2 - if vs == [] then 1 else 0) && x>=0)
324+ case choose::Int of
325+ -- Union with Empty
326+ 0 -> unionPerm (gen vs ds) (return $ Empty)
327+
328+ -- Pick some number of elements (maybe none) and create a data leaf
329+ 1 -> do i <- suchThat arbitrary (<= (length ds))
330+ unionPerm (gen vs (drop i ds)) (return $ Data (take i ds))
331+
332+ -- Case where vs is non-empty, create a variable node, and either remove that
333+ -- variable, or keep it around as a possibility again to test idempotency
334+ 2 -> oneof [unionPerm (gen (tail vs) ds) (return $ Var (head vs)),
335+ unionPerm (gen vs ds) (return $ Var (head vs))]
336+ _ -> error "unpossible"
337+
338+
339+
340+
341+
342+
343+
344+
changelog.mddeleted−5
@@ -1,5 +0,0 @@
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
example-new.hsnew file+86
@@ -0,0 +1,86 @@
1+{-# LANGUAGE DataKinds, KindSignatures, GADTs, TypeOperators, TypeFamilies, PolyKinds, EmptyDataDecls #-}
2+
3+{-# OPTIONS_GHC -fplugin=TyMap #-}
4+import TyMap
5+
6+
7+
8+
9+
10+
11+
12+
13+
14+
15+
16+
17+
18+
19+
20+
21+
22+
23+
24+
25+
26+
27+
28+
29+
30+
31+import GHC.TypeLits
32+
33+
34+data Proxy (s :: Map * (Session *)) = Proxy
35+
36+data Container (a :: *) where
37+ Empty :: Container (Set '[])
38+ Ext :: a -> Container (Set s) -> Container (Set (Union '[a] s))
39+ ExtP :: Proxy a -> Container (Set s) -> Container (Set (Union '[a] s))
40+
41+data Natural (a :: Nat) where
42+ Z :: Natural 0
43+ S :: Natural n -> Natural (n + 1)
44+
45+-- Should be typeable with the plugin
46+foo :: Container (Set '[Natural 1, Natural 2, Natural 3])
47+foo = Ext (S $ S Z) (Ext (S Z) (Ext (S $ S $ S Z) Empty))
48+
49+
50+
51+
52+
53+
54+
55+
56+
57+
58+
59+
60+
61+
62+
63+
64+
65+
66+
67+
68+
69+
70+
71+infixr 4 :->
72+data Map a b = a :-> b
73+
74+data X
75+data Y
76+
77+mkA :: Proxy (Y :-> A)
78+mkA = Proxy
79+
80+mkB :: Proxy (X :-> B)
81+mkB = Proxy
82+
83+data Session a = A | B | C a
84+
85+bar :: Container (Set '[Y :-> A, X :-> B])
86+bar = ExtP mkB (ExtP mkA Empty)
example.hs+13−25
@@ -1,31 +1,19 @@
1−{-# LANGUAGE DataKinds, TypeOperators, TypeFamilies, MultiParamTypeClasses #-}
1+{-# LANGUAGE DataKinds, TypeOperators #-}
22
3−import GHC.TypeLits
4−import Data.Type.Map
3+import Data.Type.Set
54
6−-- Specify that key-value pairs on Ints combine to an Int
7−type instance Combine Int Int = Int
8−-- Specify that Int values for matching keys should be added
9−instance Combinable Int Int where
10− combine x y = x + y
5+foo :: Set '["x" :-> Int, "z" :-> Int, "w" :-> Int]
6+foo = Ext ((Var :: (Var "x")) :-> 2) $
7+ Ext ((Var :: (Var "z")) :-> 4) $
8+ Ext ((Var :: (Var "w")) :-> 5) $
9+ Empty
1110
12−foo :: Map '["x" :-> Int, "z" :-> Bool, "w" :-> Int]
13−foo = Ext (Var :: (Var "x")) 2
14− $ Ext (Var :: (Var "z")) True
15− $ Ext (Var :: (Var "w")) 5
16− $ Empty
1711
18−foo' :: Map (AsMap '["z" :-> Bool, "x" :-> Int, "w" :-> Int])
19−foo' = asMap foo
20−
21−bar :: Map '["y" :-> Int, "w" :-> Int]
22−bar = Ext (Var :: (Var "y")) 3 $
23− Ext (Var :: (Var "w")) 1 $
24− Empty
12+bar :: Set '["y" :-> Int, "w" :-> Int]
13+bar = Ext ((Var :: (Var "y")) :-> 3) $
14+ Ext ((Var :: (Var "w")) :-> 1) $
15+ Empty
2516
2617-- GHC can easily infer this type, so an explicit signature not necessary
27−-- foobar :: Map '["w" :-> Int, "x" :-> Int, "y" :-> Integer, "z" :-> Int]
28−foobar = foo `union` bar
29−
30−foobarToFoo :: Map '["w" :-> Int, "x" :-> Int, "z" :-> Bool]
31−foobarToFoo = submap foobar
18+-- foobar :: Set '["w" :-> Int, "x" :-> Int, "y" :-> Integer, "z" :-> Int]
19+foobar = foo `union` bar
example2.hsdeleted−30
@@ -1,30 +0,0 @@
1−{-# LANGUAGE DataKinds, TypeOperators, TypeFamilies, GADTs, StandaloneDeriving #-}
2−{-# LANGUAGE FlexibleContexts #-}
3−
4−import GHC.TypeLits
5−import Data.Type.Set
6−
7−type instance Cmp (Natural n) (Natural m) = CmpNat n m
8−
9−data Natural (a :: Nat) where
10− Z :: Natural 0
11− S :: Natural n -> Natural (n + 1)
12−
13−deriving instance Show (Natural n)
14−
15−-- foo :: Set '[Natural 0, Natural 1, Natural 3]
16−foo = asSet $ Ext (S Z) (Ext (S (S (S Z))) (Ext Z Empty))
17−
18−-- bar :: Set '[Natural 1, Natural 2]
19−bar = asSet $ Ext (S (S Z)) (Ext (S Z) (Ext (S Z) Empty))
20−
21−-- foobar :: Set '[Natural 0, Natural 1, Natural 2, Natural 3]
22−foobar = 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.hsdeleted−261
@@ -1,261 +0,0 @@
1−{- This module provides type-level finite maps.
2−The implementation is similar to that shown in the paper.
3− "Embedding effect systems in Haskell" Orchard, Petricek 2014 -}
4−
5−{-# LANGUAGE TypeOperators, PolyKinds, DataKinds, KindSignatures,
6− TypeFamilies, UndecidableInstances, MultiParamTypeClasses,
7− FlexibleInstances, GADTs, FlexibleContexts, ScopedTypeVariables,
8− ConstraintKinds, IncoherentInstances #-}
9−
10−module Data.Type.Map (Mapping(..), Union, Unionable, union, Var(..), Map(..),
11− Combine, Combinable(..), Cmp,
12− Nubable, nub,
13− Lookup, Member, (:\), Split, split,
14− IsMember, lookp, Updatable, update,
15− IsMap, AsMap, asMap,
16− Submap, submap) where
17−
18−import GHC.TypeLits
19−import Data.Type.Bool
20−import Data.Type.Equality
21−import Data.Type.Set (Cmp, Proxy(..), Flag(..), Sort, Filter, (:++))
22−
23−{- Throughout, type variables
24− 'k' ranges over "keys"
25− 'v' ranges over "values"
26− 'kvp' ranges over "key-value-pairs"
27− 'm', 'n' range over "maps" -}
28−
29−-- Mappings
30−infixr 4 :->
31−{-| A key-value pair -}
32−data Mapping k v = k :-> v
33−
34−{-| Union of two finite maps -}
35−type Union m n = Nub (Sort (m :++ n))
36−
37−{-| Apply 'Combine' to values with matching key (removes duplicate keys) -}
38−type family Nub t where
39− Nub '[] = '[]
40− Nub '[kvp] = '[kvp]
41− Nub ((k :-> v1) ': (k :-> v2) ': m) = Nub ((k :-> Combine v1 v2) ': m)
42− Nub (kvp1 ': kvp2 ': s) = kvp1 ': Nub (kvp2 ': s)
43−
44−{-| Open type family for combining values in a map (that have the same key) -}
45−type family Combine (a :: v) (b :: v) :: v
46−
47−{-| Delete elements from a map by key -}
48−type family (m :: [Mapping k v]) :\ (c :: k) :: [Mapping k v] where
49− '[] :\ k = '[]
50− ((k :-> v) ': m) :\ k = m :\ k
51− (kvp ': m) :\ k = kvp ': (m :\ k)
52−
53−{-| Type-level lookup of elements from a map -}
54−type family Lookup (m :: [Mapping k v]) (c :: k) :: Maybe v where
55− Lookup '[] k = Nothing
56− Lookup ((k :-> v) ': m) k = Just v
57− Lookup (kvp ': m) k = Lookup m k
58−
59−{-| Membership test as type function -}
60−type family Member (c :: k) (m :: [Mapping k v]) :: Bool where
61− Member k '[] = False
62− Member k ((k :-> v) ': m) = True
63− Member k (kvp ': m) = Member k m
64−
65−-----------------------------------------------------------------
66−-- Value-level map with a type-level representation
67−
68−{-| Pair a symbol (representing a variable) with a type -}
69−data Var (k :: Symbol) = Var
70−
71−instance KnownSymbol k => Show (Var k) where
72− show = symbolVal
73−
74−{-| A value-level heterogenously-typed Map (with type-level representation in terms of lists) -}
75−data Map (n :: [Mapping Symbol *]) where
76− Empty :: Map '[]
77− Ext :: Var k -> v -> Map m -> Map ((k :-> v) ': m)
78−
79−{-| Membership test a type class (predicate) -}
80−class IsMember v t m where
81− {-| Value-level lookup of elements from a map, via type class predicate -}
82− lookp :: Var v -> Map m -> t
83−
84−instance {-# OVERLAPS #-} IsMember v t ((v ':-> t) ': m) where
85− lookp _ (Ext _ x _) = x
86−
87−instance {-# OVERLAPPABLE #-} IsMember v t m => IsMember v t (x ': m) where
88− lookp v (Ext _ _ m) = lookp v m
89−
90−
91−{-| Updatability as a type class -}
92−class Updatable v t m n where
93− {-| Update a map with `m` at variable `v` with a value of type `t`
94− to produce a map of type `n` -}
95− update :: Map m -> Var v -> t -> Map n
96−
97−instance {-# OVERLAPS #-} Updatable v t ((v ':-> s) ': m) ((v ':-> t) ': m) where
98− update (Ext v _ m) _ x = Ext v x m
99−
100−instance Updatable v t m n => Updatable v t ((w ':-> y) ': m) ((w ':-> y) ': n) where
101− update (Ext w y m) v x = Ext w y (update m v x)
102−
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−
109−
110−{-| Predicate to check if in normalised map form -}
111−type IsMap s = (s ~ Nub (Sort s))
112−
113−{-| At the type level, normalise the list form to the map form -}
114−type AsMap s = Nub (Sort s)
115−
116−{-| At the value level, noramlise the list form to the map form -}
117−asMap :: (Sortable s, Nubable (Sort s)) => Map s -> Map (AsMap s)
118−asMap x = nub (quicksort x)
119−
120−instance Show (Map '[]) where
121− show Empty = "{}"
122−
123−instance (KnownSymbol k, Show v, Show' (Map s)) => Show (Map ((k :-> v) ': s)) where
124− show (Ext k v s) = "{" ++ show k ++ " :-> " ++ show v ++ show' s ++ "}"
125−
126−class Show' t where
127− show' :: t -> String
128−instance Show' (Map '[]) where
129− show' Empty = ""
130−instance (KnownSymbol k, Show v, Show' (Map s)) => Show' (Map ((k :-> v) ': s)) where
131− show' (Ext k v s) = ", " ++ show k ++ " :-> " ++ show v ++ (show' s)
132−
133−instance Eq (Map '[]) where
134− Empty == Empty = True
135−
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'
144−
145−{-| Union of two finite maps (normalising) -}
146−union :: (Unionable s t) => Map s -> Map t -> Map (Union s t)
147−union s t = nub (quicksort (append s t))
148−
149−type Unionable s t = (Nubable (Sort (s :++ t)), Sortable (s :++ t))
150−
151−{-| Append of two finite maps (non normalising) -}
152−append :: Map s -> Map t -> Map (s :++ t)
153−append Empty x = x
154−append (Ext k v xs) ys = Ext k v (append xs ys)
155−
156−type instance Cmp (k :: Symbol) (k' :: Symbol) = CmpSymbol k k'
157−type instance Cmp (k :-> v) (k' :-> v') = CmpSymbol k k'
158−
159−{-| Value-level quick sort that respects the type-level ordering -}
160−class Sortable xs where
161− quicksort :: Map xs -> Map (Sort xs)
162−
163−instance Sortable '[] where
164− quicksort Empty = Empty
165−
166−instance (Sortable (Filter FMin (k :-> v) xs)
167− , Sortable (Filter FMax (k :-> v) xs)
168− , FilterV FMin k v xs
169− , FilterV FMax k v xs) => Sortable ((k :-> v) ': xs) where
170− quicksort (Ext k v xs) =
171− quicksort (less k v xs) `append` Ext k v Empty `append` quicksort (more k v xs)
172− where
173− less = filterV (Proxy::(Proxy FMin))
174− more = filterV (Proxy::(Proxy FMax))
175−
176−{- Filter out the elements less-than or greater-than-or-equal to the pivot -}
177−class FilterV (f::Flag) k v xs where
178− filterV :: Proxy f -> Var k -> v -> Map xs -> Map (Filter f (k :-> v) xs)
179−
180−instance FilterV f k v '[] where
181− filterV _ k v Empty = Empty
182−
183−instance (Conder (Cmp x (k :-> v) == LT), FilterV FMin k v xs) => FilterV FMin k v (x ': xs) where
184− filterV f@Proxy k v (Ext k' v' xs) =
185− cond (Proxy::(Proxy (Cmp x (k :-> v) == LT)))
186− (Ext k' v' (filterV f k v xs))
187− (filterV f k v xs)
188−
189−instance
190− (Conder ((Cmp x (k :-> v) == GT) || (Cmp x (k :-> v) == EQ)), FilterV FMax k v xs)
191− => FilterV FMax k v (x ': xs) where
192− filterV f@Proxy k v (Ext k' v' xs) =
193− cond (Proxy::(Proxy ((Cmp x (k :-> v) == GT) || (Cmp x (k :-> v) == EQ))))
194− (Ext k' v' (filterV f k v xs))
195− (filterV f k v xs)
196−
197−class Combinable t t' where
198− combine :: t -> t' -> Combine t t'
199−
200−class Nubable t where
201− nub :: Map t -> Map (Nub t)
202−
203−instance Nubable '[] where
204− nub Empty = Empty
205−
206−instance Nubable '[e] where
207− nub (Ext k v Empty) = Ext k v Empty
208−
209−instance {-# OVERLAPPABLE #-}
210− (Nub (e ': f ': s) ~ (e ': Nub (f ': s)),
211− Nubable (f ': s)) => Nubable (e ': f ': s) where
212− nub (Ext k v (Ext k' v' s)) = Ext k v (nub (Ext k' v' s))
213−
214−instance {-# OVERLAPS #-}
215− (Combinable v v', Nubable ((k :-> Combine v v') ': s))
216− => Nubable ((k :-> v) ': (k :-> v') ': s) where
217− nub (Ext k v (Ext k' v' s)) = nub (Ext k (combine v v') s)
218−
219−
220−class Conder g where
221− cond :: Proxy g -> Map s -> Map t -> Map (If g s t)
222−
223−instance Conder True where
224− cond _ s t = s
225−
226−instance Conder False where
227− cond _ s t = t
228−
229−
230−{-| Splitting a union of maps, given the maps we want to split it into -}
231−class Split s t st where
232− -- where st ~ Union s t
233− split :: Map st -> (Map s, Map t)
234−
235−instance Split '[] '[] '[] where
236− split Empty = (Empty, Empty)
237−
238−instance {-# OVERLAPPABLE #-} Split s t st => Split (x ': s) (x ': t) (x ': st) where
239− split (Ext k v st) = let (s, t) = split st
240− in (Ext k v s, Ext k v t)
241−
242−instance {-# OVERLAPS #-} Split s t st => Split (x ': s) t (x ': st) where
243− split (Ext k v st) = let (s, t) = split st
244− in (Ext k v s, t)
245−
246−instance {-# OVERLAPS #-} (Split s t st) => Split s (x ': t) (x ': st) where
247− split (Ext k v st) = let (s, t) = split st
248− in (s, Ext k v t)
249−
250−{-| Construct a submap 's' from a supermap 't' -}
251−class Submap s t where
252− submap :: Map t -> Map s
253−
254−instance Submap '[] '[] where
255− submap xs = Empty
256−
257−instance {-# OVERLAPPABLE #-} Submap s t => Submap s (x ': t) where
258− submap (Ext _ _ xs) = submap xs
259−
260−instance {-# OVERLAPS #-} Submap s t => Submap (x ': s) (x ': t) where
261− submap (Ext k v xs) = Ext k v (submap xs)
src/Data/Type/Set.hs+64−76
@@ -1,13 +1,11 @@
1−{-# LANGUAGE GADTs, DataKinds, KindSignatures, TypeOperators, TypeFamilies,
2− MultiParamTypeClasses, FlexibleInstances, PolyKinds,
3− FlexibleContexts, UndecidableInstances, ConstraintKinds,
4− ScopedTypeVariables, TypeInType #-}
1+{-# LANGUAGE GADTs, DataKinds, KindSignatures, TypeOperators, TypeFamilies,
2+ MultiParamTypeClasses, FlexibleInstances, PolyKinds, FlexibleContexts,
3+ UndecidableInstances, ConstraintKinds, ScopedTypeVariables #-}
54
6−module Data.Type.Set (Set(..), Union, Unionable, union, quicksort, append,
7− Sort, Sortable, (:++), Split(..), Cmp, Filter, Flag(..),
5+module Data.Type.Set (Set(..), Union, Unionable, union, quicksort, append,
6+ Sort, Sortable, Append(..), Split(..), Cmp,
87 Nub, Nubable(..), AsSet, asSet, IsSet, Subset(..),
9− Delete(..), Proxy(..), remove, Remove, (:\),
10− Member(..), NonMember, MemberP(..)) where
8+ (:->)(..), Var(..), Delete(..)) where
119
1210import GHC.TypeLits
1311import Data.Type.Bool
@@ -15,18 +13,16 @@ import Data.Type.Equality
1513
1614data Proxy (p :: k) = Proxy
1715
18−-- Value-level 'Set' representation, essentially a list
19−data Set (n :: [k]) where
20− {--| Construct an empty set -}
16+{-| Core Set definition, in terms of lists -}
17+data Set (n :: [*]) where
2118 Empty :: Set '[]
22− {--| Extend a set with an element -}
2319 Ext :: e -> Set s -> Set (e ': s)
2420
2521instance Show (Set '[]) where
2622 show Empty = "{}"
2723
2824instance (Show e, Show' (Set s)) => Show (Set (e ': s)) where
29− show (Ext e s) = "{" ++ show e ++ (show' s) ++ "}"
25+ show (Ext e s) = "{" ++ show e ++ (show' s) ++ "}"
3026
3127class Show' t where
3228 show' :: t -> String
@@ -35,10 +31,6 @@ instance Show' (Set '[]) where
3531instance (Show' (Set s), Show e) => Show' (Set (e ': s)) where
3632 show' (Ext e s) = ", " ++ show e ++ (show' s)
3733
38−instance (Eq e, Eq (Set s)) => Eq (Set (e ': s)) where
39− (Ext e m) == (Ext e' m') = e == e' && m == m'
40−
41−
4234{-| At the type level, normalise the list form to the set form -}
4335type AsSet s = Nub (Sort s)
4436
@@ -50,68 +42,54 @@ asSet x = nub (quicksort x)
5042type IsSet s = (s ~ Nub (Sort s))
5143
5244{-| Useful properties to be able to refer to someties -}
53−type SetProperties f = (Union f '[] ~ f, Split f '[] f,
54− Union '[] f ~ f, Split '[] f f,
45+type SetProperties f = (Union f '[] ~ f, Split f '[] f,
46+ Union '[] f ~ f, Split '[] f f,
5547 Union f f ~ f, Split f f f,
5648 Unionable f '[], Unionable '[] f)
5749
5850{-- Union --}
5951
6052{-| Union of sets -}
61−type Union s t = Nub (Sort (s :++ t))
53+type Union s t = Nub (Sort (Append s t))
6254
6355union :: (Unionable s t) => Set s -> Set t -> Set (Union s t)
6456union s t = nub (quicksort (append s t))
6557
66−type Unionable s t = (Sortable (s :++ t), Nubable (Sort (s :++ t)))
58+type Unionable s t = (Sortable (Append s t), Nubable (Sort (Append s t)))
6759
6860{-| List append (essentially set disjoint union) -}
69−type family (:++) (x :: [k]) (y :: [k]) :: [k] where
70− '[] :++ xs = xs
71− (x ': xs) :++ ys = x ': (xs :++ ys)
61+type family Append (s :: [k]) (t :: [k]) :: [k] where
62+ Append '[] t = t
63+ Append (x ': xs) ys = x ': (Append xs ys)
7264
73−append :: Set s -> Set t -> Set (s :++ t)
65+append :: Set s -> Set t -> Set (Append s t)
7466append Empty x = x
7567append (Ext e xs) ys = Ext e (append xs ys)
7668
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)
69+{-| Useful alias for append -}
70+type (s :: [k]) :++ (t :: [k]) = Append s t
9571
9672{-| Splitting a union a set, given the sets we want to split it into -}
9773class Split s t st where
9874 -- where st ~ Union s t
99− split :: Set st -> (Set s, Set t)
75+ split :: Set st -> (Set s, Set t)
10076
10177instance Split '[] '[] '[] where
10278 split Empty = (Empty, Empty)
10379
104−instance {-# OVERLAPPABLE #-} Split s t st => Split (x ': s) (x ': t) (x ': st) where
80+instance Split s t st => Split (x ': s) (x ': t) (x ': st) where
10581 split (Ext x st) = let (s, t) = split st
10682 in (Ext x s, Ext x t)
10783
108−instance {-# OVERLAPS #-} Split s t st => Split (x ': s) t (x ': st) where
84+instance Split s t st => Split (x ': s) t (x ': st) where
10985 split (Ext x st) = let (s, t) = split st
110− in (Ext x s, t)
86+ in (Ext x s, t)
11187
112−instance {-# OVERLAPS #-} (Split s t st) => Split s (x ': t) (x ': st) where
88+instance (Split s t st) => Split s (x ': t) (x ': st) where
11389 split (Ext x st) = let (s, t) = split st
114− in (s, Ext x t)
90+ in (s, Ext x t)
91+
92+
11593
11694{-| Remove duplicates from a sorted list -}
11795type family Nub t where
@@ -121,7 +99,7 @@ type family Nub t where
12199 Nub (e ': f ': s) = e ': Nub (f ': s)
122100
123101{-| Value-level counterpart to the type-level 'Nub'
124− Note: the value-level case for equal types is not define here,
102+ Note: the value-level case for equal types is not define here,
125103 but should be given per-application, e.g., custom 'merging' behaviour may be required -}
126104
127105class Nubable t where
@@ -136,7 +114,7 @@ instance Nubable '[e] where
136114instance Nubable (e ': s) => Nubable (e ': e ': s) where
137115 nub (Ext _ (Ext e s)) = nub (Ext e s)
138116
139−instance {-# OVERLAPS #-} (Nub (e ': f ': s) ~ (e ': Nub (f ': s)),
117+instance (Nub (e ': f ': s) ~ (e ': Nub (f ': s)),
140118 Nubable (f ': s)) => Nubable (e ': f ': s) where
141119 nub (Ext e (Ext f s)) = Ext e (nub (Ext f s))
142120
@@ -145,13 +123,13 @@ instance {-# OVERLAPS #-} (Nub (e ': f ': s) ~ (e ': Nub (f ': s)),
145123class Subset s t where
146124 subset :: Set t -> Set s
147125
148−instance Subset '[] '[] where
126+instance Subset '[] '[] where
149127 subset xs = Empty
150128
151−instance {-# OVERLAPPABLE #-} Subset s t => Subset s (x ': t) where
152− subset (Ext _ xs) = subset xs
129+instance Subset '[] (x ': t) where
130+ subset xs = Empty
153131
154−instance {-# OVERLAPS #-} Subset s t => Subset (x ': s) (x ': t) where
132+instance Subset s t => Subset (x ': s) (x ': t) where
155133 subset (Ext x xs) = Ext x (subset xs)
156134
157135
@@ -164,8 +142,8 @@ data Flag = FMin | FMax
164142
165143type family Filter (f :: Flag) (p :: k) (xs :: [k]) :: [k] where
166144 Filter f p '[] = '[]
167− Filter FMin p (x ': xs) = If (Cmp x p == LT) (x ': (Filter FMin p xs)) (Filter FMin p xs)
168− Filter FMax p (x ': xs) = If (Cmp x p == GT || Cmp x p == EQ) (x ': (Filter FMax p xs)) (Filter FMax p xs)
145+ Filter FMin p (x ': xs) = If (Cmp x p == LT) (x ': (Filter FMin p xs)) (Filter FMin p xs)
146+ Filter FMax p (x ': xs) = If (Cmp x p == GT || Cmp x p == EQ) (x ': (Filter FMax p xs)) (Filter FMax p xs)
169147
170148type family DeleteFromList (e :: elem) (list :: [elem]) where
171149 DeleteFromList elem '[] = '[]
@@ -198,11 +176,11 @@ instance FilterV f p '[] where
198176
199177instance (Conder ((Cmp x p) == LT), FilterV FMin p xs) => FilterV FMin p (x ': xs) where
200178 filterV f@Proxy p (Ext x xs) = cond (Proxy::(Proxy ((Cmp x p) == LT)))
201− (Ext x (filterV f p xs)) (filterV f p xs)
179+ (Ext x (filterV f p xs)) (filterV f p xs)
202180
203181instance (Conder (((Cmp x p) == GT) || ((Cmp x p) == EQ)), FilterV FMax p xs) => FilterV FMax p (x ': xs) where
204182 filterV f@Proxy p (Ext x xs) = cond (Proxy::(Proxy (((Cmp x p) == GT) || ((Cmp x p) == EQ))))
205− (Ext x (filterV f p xs)) (filterV f p xs)
183+ (Ext x (filterV f p xs)) (filterV f p xs)
206184
207185class Conder g where
208186 cond :: Proxy g -> Set s -> Set t -> Set (If g s t)
@@ -217,20 +195,30 @@ instance Conder False where
217195
218196type family Cmp (a :: k) (b :: k) :: Ordering
219197
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
198+{-| Pair a symbol (representing a variable) with a type -}
199+infixl 2 :->
200+data (k :: Symbol) :-> (v :: *) = (Var k) :-> v
201+
202+data Var (k :: Symbol) where Var :: Var k
203+ {- Some special defaults for some common names -}
204+ X :: Var "x"
205+ Y :: Var "y"
206+ Z :: Var "z"
207+
208+
209+instance (Show (Var k), Show v) => Show (k :-> v) where
210+ show (k :-> v) = "(" ++ show k ++ " :-> " ++ show v ++ ")"
211+instance Show (Var "x") where
212+ show X = "x"
213+ show Var = "Var"
214+instance Show (Var "y") where
215+ show Y = "y"
216+ show Var = "Var"
217+instance Show (Var "z") where
218+ show Z = "z"
219+ show Var = "Var"
220+instance Show (Var v) where
221+ show _ = "Var"
222+
223+{-| Symbol comparison -}
224+type instance Cmp (v :-> a) (u :-> b) = CmpSymbol v u
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: lts-12.7
4+resolver: lts-3.5
55
66# Local packages, usually specified by relative directory name
77packages:
type-level-sets.cabal+30−59
@@ -1,77 +1,50 @@
11name: type-level-sets
2−version: 0.8.9.0
3−synopsis: Type-level sets and finite maps (with value-level counterparts)
4−description:
5− This package provides type-level sets (no duplicates, sorted to provide a normal form) via 'Set' and type-level
6− finite maps via 'Map', with value-level counterparts.
2+version: 0.5.1
3+synopsis: Type-level sets (with value-level counterparts and various operations)
4+description:
5+ This package provides type-level sets (no duplicates, sorted to provide a nomral form) via 'Set',
6+ with value-level counterparts. Described in the paper \"Embedding effect systems in Haskell\" by Dominic Orchard
7+ and Tomas Petricek <http://www.cl.cam.ac.uk/~dao29/publ/haskell14-effects.pdf> (Haskell Symposium, 2014)
78 .
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.
9+ Here is a brief example:
1010 .
11− Here is a brief example for finite maps:
12− .
13− >
14− > import Data.Type.Map
15− >
16− > -- Specify how to combine duplicate key-value pairs for Int values
17− > type instance Combine Int Int = Int
18− > instance Combinable Int Int where
19− > combine x y = x + y
20− >
21− > 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
2611 >
27− > bar :: Map '["y" :-> Int, "w" :-> Int]
28− > bar = Ext (Var :: (Var "y")) 3
29− > $ Ext (Var :: (Var "w")) 1
30− > $ Empty
12+ > import Data.Type.Set
3113 >
32− > -- foobar :: Map '["w" :-> Int, "x" :-> Int, "y" :-> Int, "z" :-> Bool]
14+ > foo :: Set '["x" :-> Int, "z" :-> Int, "w" :-> Int]
15+ > foo = Ext ((Var :: (Var "x")) :-> 2) $
16+ > Ext ((Var :: (Var "z")) :-> 4) $
17+ > Ext ((Var :: (Var "w")) :-> 5) $
18+ > Empty
19+ >
20+ > bar :: Set '["y" :-> Int, "w" :-> Int]
21+ > bar = Ext ((Var :: (Var "y")) :-> 3) $
22+ > Ext ((Var :: (Var "w")) :-> 1) $
23+ > Empty
24+ >
25+ > -- foobar :: Set '["w" :-> Int, "x" :-> Int, "y" :-> Int, "z" :-> Int]
3326 > foobar = foo `union` bar
3427 .
35− The 'Map' type for 'foobar' here shows the normalised form (sorted with no duplicates).
28+ The 'Set' type for 'foobar' here shows the normalised form (sorted with no duplicates).
3629 The type signatures is commented out as it can be infered. Running the example we get:
3730 .
38− > >>> foobar
39− > {w :-> 6, x :-> 2, y :-> 3, z :-> True}
40− .
41− Thus, we see that the values for \"w\" are added together.
42− For sets, here is an example:
43− .
44− > import GHC.TypeLits
45− > import Data.Type.Set
46− > type instance Cmp (Natural n) (Natural m) = CmpNat n m
47− >
48− > data Natural (a :: Nat) where
49− > Z :: Natural 0
50− > S :: Natural n -> Natural (n + 1)
51− >
52− > -- foo :: Set '[Natural 0, Natural 1, Natural 3]
53− > foo = asSet $ Ext (S Z) (Ext (S (S (S Z))) (Ext Z Empty))
54− >
55− > -- bar :: Set '[Natural 1, Natural 2]
56− > bar = asSet $ Ext (S (S Z)) (Ext (S Z) (Ext (S Z) Empty))
57− >
58− > -- foobar :: Set '[Natural 0, Natural 1, Natural 2, Natural 3]
59− > foobar = foo `union` bar
31+ > >>> foobar
32+ > [(Var :-> 1), (Var :-> 2), (Var :-> 3), (Var :-> 4)]
6033 .
61− Note the types here are all inferred.
34+ Thus, we see that the first value paired with the \"w\" variable is dropped.
6235 .
6336license: BSD3
6437license-file: LICENSE
6538category: Type System, Data Structures
66−copyright: 2013-18 University of Kent
39+copyright: 2013-14 University of Cambridge
6740author: Dominic Orchard
6841maintainer: Dominic Orchard
6942stability: experimental
7043build-type: Simple
7144cabal-version: >= 1.6
72−tested-with: GHC >= 8.2.2
45+tested-with: GHC == 7.8.2
7346
74−extra-source-files: example.hs, example2.hs, changelog.md
47+extra-source-files: example.hs
7548
7649
7750source-repository head
@@ -80,11 +53,9 @@ source-repository head
8053
8154library
8255 hs-source-dirs: src
83− other-extensions: TypeInType
8456
8557
8658 exposed-modules: Data.Type.Set
87− Data.Type.Map
88−
89− build-depends: base < 5,
90− ghc-prim
59+
60+ build-depends: base >= 4.7.0.0 && < 5,
61+ ghc-prim