git.iko.soy/type-level-sets
on 2d24897 help sign in
11 files changed+567−252
since splitsnapshots
unifiedsplit
README+21−42 TySet.hs+355 changelog.md−5 example-new.hs+61 example-set.hs+39 example.hs+11−12 example2.hs−9 src/Data/Type/Map.hs+25−82 src/Data/Type/Set.hs+29−70 stack.yaml+1−1 type-level-sets.cabal+25−31
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+355
@@ -0,0 +1,355 @@
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, ppr) 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+printerS = let ?ifDebug = True in tcPluginIO . debug . showSDocUnsafe . ppCts
86+printer = let ?ifDebug = True in tcPluginIO . debug
87+
88+pluginSolve :: () -> [Ct] -> [Ct] -> [Ct] -> TcPluginM TcPluginResult
89+pluginSolve () given derived wanted =
90+ let ?ifDebug = True in
91+
92+ do tcPluginIO $ debug "*****************************"
93+ tcPluginIO $ debug "Running TySet equality plugin"
94+ --debug $ ppCts wanted
95+ tcPluginIO $ debug $ showSDocUnsafe $ ppCts wanted
96+ tcPluginIO $ debug "Givens"
97+ --debug $ ppCts given
98+ tcPluginIO $ debug $ showSDocUnsafe $ ppCts given
99+ tcPluginIO $ debug "Derived"
100+ -- debug $ ppCts derived
101+ tcPluginIO $ debug $ showSDocUnsafe $ ppCts derived
102+ -- debug $ ppr $ head $ wanted
103+
104+ --solved <- findEmptySetEquality wanted
105+ (solved, generated) <- findSetEquality wanted
106+ printer "Done - solved"
107+ printerS (map snd solved)
108+ printer "DOne - generated"
109+ printerS generated
110+
111+ return $ TcPluginOk solved generated
112+
113+pluginStop :: () -> TcPluginM ()
114+pluginStop _ = return ()
115+
116+-- Pretty print constraints
117+ppCts [] = text "(empty)"
118+ppCts cs = vcat (map ppr cs)
119+
120+{- Some debugging Show instances to help me understand what is coming in and out of GHC -}
121+deriving instance Show TyLit
122+deriving instance Show Type
123+instance Show Var where
124+ show v = showSDocUnsafe $ ppr v
125+instance Show TyCon where
126+ show tycon = showSDocUnsafe $ ppr tycon
127+instance Show Ct where
128+ show ct = showSDocUnsafe $ ppr ct
129+
130+{-
131+-- Prediacate one whether a type is = Set '[]
132+isEmptySetType t = do (x, tcs) <- splitTyConApp_maybe t
133+ guard $ length tcs == 2
134+ guard $ getOccString (tyConName x) == "Set"
135+ case tcs of [TyVarTy k, TyConApp con [TyVarTy k']] ->
136+ do guard $ k == k'
137+ guard $ (getOccString . tyConName $ con) == "[]"
138+ _ -> Nothing
139+-}
140+
141+getNameStr = getOccString . tyConName
142+
143+liftTc :: Maybe a -> MaybeT TcPluginM a
144+liftTc = MaybeT . return
145+
146+liftMt :: TcPluginM a -> MaybeT TcPluginM a
147+liftMt x = MaybeT (fmap Just x)
148+
149+findSetEquality :: [Ct] -> TcPluginM ([(EvTerm, Ct)], [Ct])
150+findSetEquality [] = return ([], [])
151+findSetEquality (ct : xs) =
152+ do x <- runMaybeT $
153+ do (Nominal, t1, t2) <- liftTc $ getEqPredTys_maybe (ctPred ct)
154+ a <- liftTc $ listTypeToTerm t1
155+ b <- "sofar sogood" `trace` liftTc $ listTypeToTerm t2
156+ (show (t1, a, t2, b)) `trace`
157+ if (a == b) then
158+ "are equal" `trace` return $ Left (EvCoercion $ TcRefl Nominal t1, ct)
159+ else -- not equal, try to find an mgu and generate conditions on that
160+ let ?ctLoc = ctLoc ct in
161+ do unifiers <- "not equal" `trace` mgu a b
162+ case unifiers of
163+ Left unifiers -> ("L unifiers: \n" ++ show unifiers) `trace` return $ Right []
164+ Right (dataUnifiers, unsolvedExtra) -> ("data unifiers:" ++ (show $ dataUnifiers)) `trace` return $ Right $ (EvCoercion $ TcRefl Nominal t1, ct) : map (\c -> (EvCoercion $ TcRefl Nominal undefined, c)) dataUnifiers
165+
166+ (solved, generated) <- findSetEquality xs
167+ case x of
168+ Just y -> case y of
169+ Left (ev, ct) -> return $ ((ev, ct) : solved, generated)
170+ Right cts -> return $ (solved ++ cts, generated)
171+ Nothing -> return (solved, generated)
172+
173+listTypeToTerm :: Type -> Maybe (TermTree Type)
174+listTypeToTerm t = case (splitTyConApp_maybe t) of
175+ Just (tcon, args) ->
176+ case getNameStr tcon of
177+ "Union" -> do guard $ (length args) >= 3
178+ (_ : (t1 : (t2 : ts))) <- return args
179+ t1' <- listTypeToTerm t1
180+ t2' <- listTypeToTerm t2
181+ return $ Union t1' t2'
182+ -- this case is probably temporary [see SessionListE.hs]
183+ ":++" -> do guard $ (length args) >= 3
184+ (_ : (t1 : (t2 : ts))) <- return args
185+ t1' <- listTypeToTerm t1
186+ t2' <- listTypeToTerm t2
187+ return $ Union t1' t2'
188+ ":" -> do guard $ (length args >= 2)
189+ (t1 : (t2 : ts)) <- return args
190+ (kind, args) <- splitTyConApp_maybe $ t1
191+ ts' <- listTypeToTerm $ head ts -- possible bug here
192+ return $ Union (Data [t2]) ts'
193+ "[]" -> do guard $ (length args == 1)
194+ [t] <- return args
195+ (kind, args) <- splitTyConApp_maybe $ t
196+ return $ Empty
197+
198+ _ -> return $ Empty -- Data [t]
199+ _ -> case t of
200+ TyVarTy v -> return $ Var $ v
201+
202+-- Representation for solving equalities on terms comprising union, data, and variables
203+
204+data TermTree a = Union (TermTree a) (TermTree a) | Empty | Var Var | Data [a] deriving Show
205+
206+-- if the second argument is a prefix of the first argument, then return Just of the suffix, else Nothing
207+dropPrefix :: Eq a => [a] -> [a] -> Maybe [a]
208+dropPrefix [] xs = Just []
209+dropPrefix xs [] = Just xs
210+dropPrefix (x:xs) (y:ys) | x == y = dropPrefix xs ys
211+ | otherwise = Nothing
212+
213+mguDataVars :: [a] -> [Var] -> Maybe [(Var, TermTree a)]
214+mguDataVars suffix [] = Nothing -- No variables to unify with
215+mguDataVars suffix (v:vs) = Just $ [(v, Data suffix)] ++ map (\v' -> (v', Var v)) vs
216+
217+mgu :: (?ctLoc :: CtLoc) => TermTree Type -> TermTree Type -> MaybeT TcPluginM (Either [(Var, TermTree Type)] ([Ct], ([Type], [Type]))) -- last component should be some equalities
218+mgu t1 t2 = let (vs1, ds1) = normalisedRep t1
219+ (vs2, ds2) = normalisedRep t2
220+ in ("----> " ++ show (ds1, ds2)) `trace`
221+ (show $ dropPrefix ds1 ds2) `trace`
222+ case (dropPrefix ds1 ds2) of
223+ Nothing -> case (dropPrefix ds2 ds1) of
224+ Nothing -> "el zilcho primo" `trace` do x <- liftMt (zipMatch ds1 ds2)
225+ return $ Right x -- ([], ([], []))
226+ Just suffix_ds2 -> "suffix_ds2" `trace`
227+ do x <- liftTc $ mguDataVars suffix_ds2 vs1
228+ return $ Left x
229+ Just suffix_ds1 -> ("suffix_ds1 " ++ (show suffix_ds1))
230+ `trace`
231+ if (suffix_ds1 == []) then
232+ do x <- liftMt (zipMatch ds1 ds2)
233+ ("zipm: ds1 = " ++ (show ds1) ++ " ds2 = " ++ (show ds2) ++ ": " ++ (show x)) `trace` return $ Right x -- ([], ([], []))
234+ else
235+ do x <- liftTc $ mguDataVars suffix_ds1 vs2
236+ return $ Left x
237+
238+mkEqualities :: (?ctLoc :: CtLoc) => [(Type, Type)] -> TcPluginM [Ct]
239+mkEqualities xs = (mapM (\(x, y) -> mkCt x y) xs) -- >>= (return . concat)
240+
241+mkCt t t' = fmap mkNonCanonical (newDerived ?ctLoc (uncurry mkPrimEqPred (t,t')))
242+
243+mkEqualities' (AppTy t1 t2) (AppTy t1' t2') = do ct <- mkCt t1 t1'
244+ ct' <- mkCt t2 t2'
245+ return [ct, ct']
246+mkEqualities' (TyConApp con kt) (TyConApp con' kt') | con == con' = mapM (uncurry mkCt) (zip kt kt')
247+mkEqualities' (FunTy t1 t2) (FunTy t1' t2') = do ct <- mkCt t1 t1'
248+ ct' <- mkCt t2 t2'
249+ return [ct, ct']
250+mkEqualities' (ForAllTy v t) (ForAllTy v' t') | v == v' = do ct <- mkCt t t'
251+ return [ct]
252+mkEqualities' t t' = do ct <- mkCt t t'
253+ return [ct]
254+
255+
256+
257+
258+zipMatch :: (?ctLoc :: CtLoc) => [Type] -> [Type] -> TcPluginM ([Ct], ([Type], [Type]))
259+zipMatch xs ys = let (unifiers, restL, restR) = zipMatch' xs ys
260+ in do unifiers' <- mkEqualities unifiers
261+ return $ (unifiers', (restL, restR))
262+
263+zipMatch' :: [a] -> [a] -> ([(a, a)], [a], [a])
264+zipMatch' [] xs = ([], [], xs)
265+zipMatch' xs [] = ([], xs, [])
266+zipMatch' (x:xs) (y:ys) = let (zips, l, r) = zipMatch' xs ys
267+ in ((x, y) : zips, l, r)
268+
269+
270+
271+
272+
273+
274+subst :: TermTree a -> [(Var, TermTree a)] -> TermTree a
275+subst (Union s t) theta = Union (subst s theta) (subst t theta)
276+subst (Var a) theta = case (lookup a theta) of
277+ Just t -> t
278+ Nothing -> Var a
279+subst t theta = t
280+
281+instance Eq a => Eq (TermTree a) where
282+ t1 == t2 = let (vs1, ds1) = normalisedRep t1
283+ (vs2, ds2) = normalisedRep t2
284+ in ("vars = " ++ (show (vs1, vs2)) ++ " eq = " ++ (show (vs1 == vs2)))
285+ `trace` (vs1 == vs2) && (all (flip elem $ ds2) ds1) && (all (flip elem $ ds1) ds2)
286+
287+normalisedRep :: Eq a => TermTree a -> ([Var], [a])
288+normalisedRep t = let (vs, ds) = separate t
289+ in (nub . sort $ vs, nub ds)
290+
291+separate :: TermTree a -> ([Var], [a])
292+separate Empty = ([], [])
293+separate (Var s) = ([s], [])
294+separate (Data xs) = ([], xs)
295+separate (Union a b) = let (vs1, ds1) = separate a
296+ (vs2, ds2) = separate b
297+ in (vs1++vs2, ds1++ds2)
298+
299+{-- Unit testing of normaliser and set equality --}
300+testSetTermEquality :: IO ()
301+testSetTermEquality = quickCheck (\((n, m) :: (TermTree Int, TermTree Int)) -> n == m)
302+
303+mkVar :: String -> Var
304+mkVar = undefined
305+
306+instance {-# OVERLAPS #-} Arbitrary (TermTree Int, TermTree Int) where
307+ arbitrary = sized $ \vars ->
308+ sized $ \datums ->
309+ do v0 <- (vector vars)::(Gen [String])
310+ v <- return $ map mkVar v0
311+ dat <- (vector datums)::(Gen [Int])
312+ v' <- shuffle v
313+ dat' <- shuffle dat
314+ g1 <- gen v dat
315+ g2 <- gen v' dat'
316+
317+ -- Soundness check on generated tree
318+ let (v0, dat0) = separate g1
319+ (v1, dat1) = separate g2
320+ norm :: (Ord a) => [a] -> [a]
321+ norm = nub . sort
322+
323+ if and [(norm v0) == (norm v), (norm v1) == (norm v),
324+ (norm dat) == (norm dat0), (norm dat) == (norm dat1)]
325+ then return ()
326+ else error $ "Generated trees failed soundness check: " ++ (show g1) ++ " " ++ (show g2)
327+ return (g1, g2)
328+
329+-- Arbitrarily permute a union of two generators
330+unionPerm x y = do x' <- x
331+ y' <- y
332+ elements [Union x' y', Union y' x']
333+
334+-- Generates arbitrary terms from a list of variables and list of Int adtums
335+gen :: [Var] -> [Int] -> Gen (TermTree Int)
336+gen [] [] = return $ Empty
337+gen vs ds = do -- Choose between 0 and 1 if 'vs' is empty, or 0-2 if 'vs' has elements
338+ choose <- suchThat arbitrary (\x -> x<=(2 - if vs == [] then 1 else 0) && x>=0)
339+ case choose::Int of
340+ -- Union with Empty
341+ 0 -> unionPerm (gen vs ds) (return $ Empty)
342+
343+ -- Pick some number of elements (maybe none) and create a data leaf
344+ 1 -> do i <- suchThat arbitrary (<= (length ds))
345+ unionPerm (gen vs (drop i ds)) (return $ Data (take i ds))
346+
347+ -- Case where vs is non-empty, create a variable node, and either remove that
348+ -- variable, or keep it around as a possibility again to test idempotency
349+ 2 -> oneof [unionPerm (gen (tail vs) ds) (return $ Var (head vs)),
350+ unionPerm (gen vs ds) (return $ Var (head vs))]
351+ _ -> error "unpossible"
352+
353+
354+
355+
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+61
@@ -0,0 +1,61 @@
1+{-# LANGUAGE DataKinds, KindSignatures, GADTs, TypeOperators, TypeFamilies, PolyKinds, EmptyDataDecls #-}
2+
3+{-# OPTIONS_GHC -fplugin=TyMap #-}
4+import TyMap
5+
6+import GHC.TypeLits
7+
8+
9+data Proxy (s :: Map * (Session *)) = Proxy
10+
11+data Container (a :: *) where
12+ Empty :: Container (Set '[])
13+ Ext :: a -> Container (Set s) -> Container (Set (Union '[a] s))
14+ ExtP :: Proxy a -> Container (Set s) -> Container (Set (Union '[a] s))
15+
16+data Natural (a :: Nat) where
17+ Z :: Natural 0
18+ S :: Natural n -> Natural (n + 1)
19+
20+-- Should be typeable with the plugin
21+foo :: Container (Set '[Natural 1, Natural 2, Natural 3])
22+foo = Ext (S $ S Z) (Ext (S Z) (Ext (S $ S $ S Z) Empty))
23+
24+
25+
26+
27+
28+
29+
30+
31+
32+
33+
34+
35+
36+
37+
38+
39+
40+
41+
42+
43+
44+
45+
46+infixr 4 :->
47+data Map a b = a :-> b
48+
49+data X
50+data Y
51+
52+mkA :: Proxy (Y :-> A)
53+mkA = Proxy
54+
55+mkB :: Proxy (X :-> B)
56+mkB = Proxy
57+
58+data Session a = A | B | C a
59+
60+bar :: Container (Set '[Y :-> A, X :-> B])
61+bar = ExtP mkB (ExtP mkA Empty)
example-set.hsnew file+39
@@ -0,0 +1,39 @@
1+{-# LANGUAGE DataKinds, KindSignatures, GADTs, TypeOperators, TypeFamilies, PolyKinds, EmptyDataDecls, StandaloneDeriving #-}
2+{-# OPTIONS_GHC -fplugin=TySet #-}
3+
4+import GHC.TypeLits
5+import TySet
6+
7+data Container (a :: *) where
8+ Empty :: Container (Set '[])
9+ Ext :: Show a => a -> Container (Set s) -> Container (Set (Union '[a] s))
10+
11+instance Show (Container a) where
12+ show Empty = "Empty"
13+ show (Ext x xs) = "Ext " ++ show x ++ " " ++ show xs
14+
15+data Natural (a :: Nat) where
16+ Z :: Natural 0
17+ S :: Natural n -> Natural (n + 1)
18+
19+instance Show (Natural a) where
20+ show Z = "Z"
21+ show (S n) = "S " ++ (show n)
22+
23+-- Should be typeable with the plugin
24+
25+foo :: Container (Set '[Natural 3, Natural 2, Natural 1])
26+foo = Ext (S $ S Z) (Ext (S Z) (Ext (S $ S $ S Z) Empty))
27+
28+foo2 :: Container (Set '[Natural 2, Natural 1])
29+foo2 = Ext (S $ S Z) (Ext (S Z) Empty)
30+
31+bar :: (Container (Set '[Natural 2, Natural 1])) -> Container (Set '[Natural 1])
32+bar (Ext (S (S Z)) (Ext (S Z) Empty)) = Ext (S Z) Empty
33+bar (Ext (S Z) (Ext (S (S Z)) Empty)) = Ext (S Z) Empty
34+
35+{-
36+dup :: Container (Set s) -> Container (Set (Union s s))
37+dup Empty = Empty
38+dup (Ext x xs) = Ext x (Ext x (dup xs))
39+-}
example.hs+11−12
@@ -1,6 +1,7 @@
1−{-# LANGUAGE DataKinds, TypeOperators, TypeFamilies, MultiParamTypeClasses #-}
1+{-# LANGUAGE DataKinds, TypeOperators, KindSignatures, TypeFamilies, MultiParamTypeClasses #-}
22
33import GHC.TypeLits
4+import Data.Type.Set (subset)
45import Data.Type.Map
56
67-- Specify that key-value pairs on Ints combine to an Int
@@ -8,24 +9,22 @@ type instance Combine Int Int = Int
89-- Specify that Int values for matching keys should be added
910instance Combinable Int Int where
1011 combine x y = x + y
12+
13+foo :: Map '["x" :-> Int, "z" :-> Int, "w" :-> Int]
14+foo = Ext (Var :: (Var "x")) 2 $
15+ Ext (Var :: (Var "z")) 4 $
16+ Ext (Var :: (Var "w")) 5 $
17+ Empty
1118
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
17−
18−foo' :: Map (AsMap '["z" :-> Bool, "x" :-> Int, "w" :-> Int])
19−foo' = asMap foo
2019
2120bar :: Map '["y" :-> Int, "w" :-> Int]
2221bar = Ext (Var :: (Var "y")) 3 $
2322 Ext (Var :: (Var "w")) 1 $
24− Empty
23+ Empty
2524
2625-- GHC can easily infer this type, so an explicit signature not necessary
2726-- foobar :: Map '["w" :-> Int, "x" :-> Int, "y" :-> Integer, "z" :-> Int]
2827foobar = foo `union` bar
2928
30−foobarToFoo :: Map '["w" :-> Int, "x" :-> Int, "z" :-> Bool]
31−foobarToFoo = submap foobar
29+foobarToFoo :: Map '["x" :-> Int, "z" :-> Int, "w" :-> Int]
30+foobarToFoo = subset foobar
example2.hs−9
@@ -1,5 +1,4 @@
11{-# LANGUAGE DataKinds, TypeOperators, TypeFamilies, GADTs, StandaloneDeriving #-}
2−{-# LANGUAGE FlexibleContexts #-}
32
43import GHC.TypeLits
54import Data.Type.Set
@@ -20,11 +19,3 @@ bar = asSet $ Ext (S (S Z)) (Ext (S Z) (Ext (S Z) Empty))
2019
2120-- foobar :: Set '[Natural 0, Natural 1, Natural 2, Natural 3]
2221foobar = 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+25−82
@@ -5,14 +5,12 @@ The implementation is similar to that shown in the paper.
55{-# LANGUAGE TypeOperators, PolyKinds, DataKinds, KindSignatures,
66 TypeFamilies, UndecidableInstances, MultiParamTypeClasses,
77 FlexibleInstances, GADTs, FlexibleContexts, ScopedTypeVariables,
8− ConstraintKinds, IncoherentInstances #-}
8+ ConstraintKinds #-}
99
1010module Data.Type.Map (Mapping(..), Union, Unionable, union, Var(..), Map(..),
1111 Combine, Combinable(..), Cmp,
1212 Nubable, nub,
13− Lookup, Member, (:\), Split, split,
14− IsMember, lookp, Updatable, update,
15− IsMap, AsMap, asMap,
13+ Lookup, Member, (:\), Split, split, IsMap,
1614 Submap, submap) where
1715
1816import GHC.TypeLits
@@ -46,17 +44,17 @@ type family Combine (a :: v) (b :: v) :: v
4644
4745{-| Delete elements from a map by key -}
4846type 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)
47+ '[] :\ k = '[]
48+ ((k :-> v) ': m) :\ k = m :\ k
49+ (kvp ': m) :\ k = kvp ': (m :\ k)
5250
53−{-| Type-level lookup of elements from a map -}
51+{-| Lookup elements from a map -}
5452type family Lookup (m :: [Mapping k v]) (c :: k) :: Maybe v where
5553 Lookup '[] k = Nothing
5654 Lookup ((k :-> v) ': m) k = Just v
5755 Lookup (kvp ': m) k = Lookup m k
5856
59−{-| Membership test as type function -}
57+{-| Membership test -}
6058type family Member (c :: k) (m :: [Mapping k v]) :: Bool where
6159 Member k '[] = False
6260 Member k ((k :-> v) ': m) = True
@@ -76,37 +74,6 @@ data Map (n :: [Mapping Symbol *]) where
7674 Empty :: Map '[]
7775 Ext :: Var k -> v -> Map m -> Map ((k :-> v) ': m)
7876
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−
11077{-| Predicate to check if in normalised map form -}
11178type IsMap s = (s ~ Nub (Sort s))
11279
@@ -121,7 +88,7 @@ instance Show (Map '[]) where
12188 show Empty = "{}"
12289
12390instance (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 ++ "}"
91+ show (Ext k v s) = "{" ++ show k ++ " :-> " ++ show v ++ (show' s) ++ "}"
12592
12693class Show' t where
12794 show' :: t -> String
@@ -130,25 +97,12 @@ instance Show' (Map '[]) where
13097instance (KnownSymbol k, Show v, Show' (Map s)) => Show' (Map ((k :-> v) ': s)) where
13198 show' (Ext k v s) = ", " ++ show k ++ " :-> " ++ show v ++ (show' s)
13299
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) -}
100+{-| Union of two finite maps -}
146101union :: (Unionable s t) => Map s -> Map t -> Map (Union s t)
147102union s t = nub (quicksort (append s t))
148103
149104type Unionable s t = (Nubable (Sort (s :++ t)), Sortable (s :++ t))
150105
151−{-| Append of two finite maps (non normalising) -}
152106append :: Map s -> Map t -> Map (s :++ t)
153107append Empty x = x
154108append (Ext k v xs) ys = Ext k v (append xs ys)
@@ -163,15 +117,11 @@ class Sortable xs where
163117instance Sortable '[] where
164118 quicksort Empty = Empty
165119
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))
120+instance (Sortable (Filter FMin (k :-> v) xs),
121+ Sortable (Filter FMax (k :-> v) xs), FilterV FMin k v xs, FilterV FMax k v xs) => Sortable ((k :-> v) ': xs) where
122+ quicksort (Ext k v xs) = ((quicksort (less k v xs)) `append` (Ext k v Empty)) `append` (quicksort (more k v xs))
123+ where less = filterV (Proxy::(Proxy FMin))
124+ more = filterV (Proxy::(Proxy FMax))
175125
176126{- Filter out the elements less-than or greater-than-or-equal to the pivot -}
177127class FilterV (f::Flag) k v xs where
@@ -180,19 +130,13 @@ class FilterV (f::Flag) k v xs where
180130instance FilterV f k v '[] where
181131 filterV _ k v Empty = Empty
182132
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)
133+instance (Conder ((Cmp x (k :-> v)) == LT), FilterV FMin k v xs) => FilterV FMin k v (x ': xs) where
134+ filterV f@Proxy k v (Ext k' v' xs) = cond (Proxy::(Proxy ((Cmp x (k :-> v)) == LT)))
135+ (Ext k' v' (filterV f k v xs)) (filterV f k v xs)
188136
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)
137+instance (Conder (((Cmp x (k :-> v)) == GT) || ((Cmp x (k :-> v)) == EQ)), FilterV FMax k v xs) => FilterV FMax k v (x ': xs) where
138+ filterV f@Proxy k v (Ext k' v' xs) = cond (Proxy::(Proxy (((Cmp x (k :-> v)) == GT) || ((Cmp x (k :-> v)) == EQ))))
139+ (Ext k' v' (filterV f k v xs)) (filterV f k v xs)
196140
197141class Combinable t t' where
198142 combine :: t -> t' -> Combine t t'
@@ -206,16 +150,15 @@ instance Nubable '[] where
206150instance Nubable '[e] where
207151 nub (Ext k v Empty) = Ext k v Empty
208152
209−instance {-# OVERLAPPABLE #-}
153+instance {-# OVERLAPPING #-}
154+ (Combinable v v', Nubable ((k :-> Combine v v') ': s)) => Nubable ((k :-> v) ': (k :-> v') ': s) where
155+ nub (Ext k v (Ext k' v' s)) = nub (Ext k (combine v v') s)
156+
157+instance {-# OVERLAPPING #-}
210158 (Nub (e ': f ': s) ~ (e ': Nub (f ': s)),
211159 Nubable (f ': s)) => Nubable (e ': f ': s) where
212160 nub (Ext k v (Ext k' v' s)) = Ext k v (nub (Ext k' v' s))
213161
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−
219162
220163class Conder g where
221164 cond :: Proxy g -> Map s -> Map t -> Map (If g s t)
src/Data/Type/Set.hs+29−70
@@ -1,13 +1,10 @@
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(..),
8− Nub, Nubable(..), AsSet, asSet, IsSet, Subset(..),
9− Delete(..), Proxy(..), remove, Remove, (:\),
10− Member(..), NonMember, MemberP(..)) where
5+module Data.Type.Set (Set(..), Union, Unionable, union, quicksort, append,
6+ Sort, Sortable, (:++), Split(..), Cmp, Filter, Flag(..),
7+ Nub, Nubable(..), AsSet, asSet, IsSet, Subset(..), Delete(..), Proxy(..)) where
118
129import GHC.TypeLits
1310import Data.Type.Bool
@@ -15,10 +12,10 @@ import Data.Type.Equality
1512
1613data Proxy (p :: k) = Proxy
1714
18−-- Value-level 'Set' representation, essentially a list
19−data Set (n :: [k]) where
15+-- Value-level 'Set' representation, essentially a list
16+data Set (n :: [*]) where
2017 {--| Construct an empty set -}
21− Empty :: Set '[]
18+ Empty :: Set '[]
2219 {--| Extend a set with an element -}
2320 Ext :: e -> Set s -> Set (e ': s)
2421
@@ -26,7 +23,7 @@ instance Show (Set '[]) where
2623 show Empty = "{}"
2724
2825instance (Show e, Show' (Set s)) => Show (Set (e ': s)) where
29− show (Ext e s) = "{" ++ show e ++ (show' s) ++ "}"
26+ show (Ext e s) = "{" ++ show e ++ (show' s) ++ "}"
3027
3128class Show' t where
3229 show' :: t -> String
@@ -35,10 +32,6 @@ instance Show' (Set '[]) where
3532instance (Show' (Set s), Show e) => Show' (Set (e ': s)) where
3633 show' (Ext e s) = ", " ++ show e ++ (show' s)
3734
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−
4235{-| At the type level, normalise the list form to the set form -}
4336type AsSet s = Nub (Sort s)
4437
@@ -50,8 +43,8 @@ asSet x = nub (quicksort x)
5043type IsSet s = (s ~ Nub (Sort s))
5144
5245{-| 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,
46+type SetProperties f = (Union f '[] ~ f, Split f '[] f,
47+ Union '[] f ~ f, Split '[] f f,
5548 Union f f ~ f, Split f f f,
5649 Unionable f '[], Unionable '[] f)
5750
@@ -74,44 +67,27 @@ append :: Set s -> Set t -> Set (s :++ t)
7467append Empty x = x
7568append (Ext e xs) ys = Ext e (append xs ys)
7669
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−
9670{-| Splitting a union a set, given the sets we want to split it into -}
9771class Split s t st where
9872 -- where st ~ Union s t
99− split :: Set st -> (Set s, Set t)
73+ split :: Set st -> (Set s, Set t)
10074
10175instance Split '[] '[] '[] where
10276 split Empty = (Empty, Empty)
10377
104−instance {-# OVERLAPPABLE #-} Split s t st => Split (x ': s) (x ': t) (x ': st) where
78+instance Split s t st => Split (x ': s) (x ': t) (x ': st) where
10579 split (Ext x st) = let (s, t) = split st
10680 in (Ext x s, Ext x t)
10781
108−instance {-# OVERLAPS #-} Split s t st => Split (x ': s) t (x ': st) where
82+instance Split s t st => Split (x ': s) t (x ': st) where
10983 split (Ext x st) = let (s, t) = split st
110− in (Ext x s, t)
84+ in (Ext x s, t)
11185
112−instance {-# OVERLAPS #-} (Split s t st) => Split s (x ': t) (x ': st) where
86+instance (Split s t st) => Split s (x ': t) (x ': st) where
11387 split (Ext x st) = let (s, t) = split st
114− in (s, Ext x t)
88+ in (s, Ext x t)
89+
90+
11591
11692{-| Remove duplicates from a sorted list -}
11793type family Nub t where
@@ -121,7 +97,7 @@ type family Nub t where
12197 Nub (e ': f ': s) = e ': Nub (f ': s)
12298
12399{-| Value-level counterpart to the type-level 'Nub'
124− Note: the value-level case for equal types is not define here,
100+ Note: the value-level case for equal types is not define here,
125101 but should be given per-application, e.g., custom 'merging' behaviour may be required -}
126102
127103class Nubable t where
@@ -136,7 +112,7 @@ instance Nubable '[e] where
136112instance Nubable (e ': s) => Nubable (e ': e ': s) where
137113 nub (Ext _ (Ext e s)) = nub (Ext e s)
138114
139−instance {-# OVERLAPS #-} (Nub (e ': f ': s) ~ (e ': Nub (f ': s)),
115+instance {-# OVERLAPS #-} (Nub (e ': f ': s) ~ (e ': Nub (f ': s)),
140116 Nubable (f ': s)) => Nubable (e ': f ': s) where
141117 nub (Ext e (Ext f s)) = Ext e (nub (Ext f s))
142118
@@ -145,13 +121,13 @@ instance {-# OVERLAPS #-} (Nub (e ': f ': s) ~ (e ': Nub (f ': s)),
145121class Subset s t where
146122 subset :: Set t -> Set s
147123
148−instance Subset '[] '[] where
124+instance Subset '[] '[] where
149125 subset xs = Empty
150126
151−instance {-# OVERLAPPABLE #-} Subset s t => Subset s (x ': t) where
127+instance Subset s t => Subset s (x ': t) where
152128 subset (Ext _ xs) = subset xs
153129
154−instance {-# OVERLAPS #-} Subset s t => Subset (x ': s) (x ': t) where
130+instance Subset s t => Subset (x ': s) (x ': t) where
155131 subset (Ext x xs) = Ext x (subset xs)
156132
157133
@@ -164,8 +140,8 @@ data Flag = FMin | FMax
164140
165141type family Filter (f :: Flag) (p :: k) (xs :: [k]) :: [k] where
166142 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)
143+ Filter FMin p (x ': xs) = If (Cmp x p == LT) (x ': (Filter FMin p xs)) (Filter FMin p xs)
144+ Filter FMax p (x ': xs) = If (Cmp x p == GT || Cmp x p == EQ) (x ': (Filter FMax p xs)) (Filter FMax p xs)
169145
170146type family DeleteFromList (e :: elem) (list :: [elem]) where
171147 DeleteFromList elem '[] = '[]
@@ -198,11 +174,11 @@ instance FilterV f p '[] where
198174
199175instance (Conder ((Cmp x p) == LT), FilterV FMin p xs) => FilterV FMin p (x ': xs) where
200176 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)
177+ (Ext x (filterV f p xs)) (filterV f p xs)
202178
203179instance (Conder (((Cmp x p) == GT) || ((Cmp x p) == EQ)), FilterV FMax p xs) => FilterV FMax p (x ': xs) where
204180 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)
181+ (Ext x (filterV f p xs)) (filterV f p xs)
206182
207183class Conder g where
208184 cond :: Proxy g -> Set s -> Set t -> Set (If g s t)
@@ -217,20 +193,3 @@ instance Conder False where
217193
218194type family Cmp (a :: k) (b :: k) :: Ordering
219195
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: lts-12.7
4+resolver: lts-3.5
55
66# Local packages, usually specified by relative directory name
77packages:
type-level-sets.cabal+25−31
@@ -1,44 +1,39 @@
11name: type-level-sets
2−version: 0.8.9.0
2+version: 0.7
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
1515 >
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
16+ > foo :: Map '["x" :-> Int, "z" :-> Int, "w" :-> Int]
17+ > foo = Ext ((Var :: (Var "x")) :-> 2) $
18+ > Ext ((Var :: (Var "z")) :-> 4) $
19+ > Ext ((Var :: (Var "w")) :-> 5) $
20+ > Empty
2621 >
2722 > bar :: Map '["y" :-> Int, "w" :-> Int]
28− > bar = Ext (Var :: (Var "y")) 3
29− > $ Ext (Var :: (Var "w")) 1
30− > $ Empty
31− >
32− > -- foobar :: Map '["w" :-> Int, "x" :-> Int, "y" :-> Int, "z" :-> Bool]
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" :-> Int]
3328 > foobar = foo `union` bar
3429 .
35− The 'Map' type for 'foobar' here shows the normalised form (sorted with no duplicates).
30+ The 'Set' type for 'foobar' here shows the normalised form (sorted with no duplicates).
3631 The type signatures is commented out as it can be infered. Running the example we get:
3732 .
38− > >>> foobar
39− > {w :-> 6, x :-> 2, y :-> 3, z :-> True}
33+ > >>> foobar
34+ > [(Var :-> 1), (Var :-> 2), (Var :-> 3), (Var :-> 4)]
4035 .
41− Thus, we see that the values for \"w\" are added together.
36+ Thus, we see that the first value paired with the \"w\" variable is dropped.
4237 For sets, here is an example:
4338 .
4439 > import GHC.TypeLits
@@ -48,7 +43,7 @@ description:
4843 > data Natural (a :: Nat) where
4944 > Z :: Natural 0
5045 > S :: Natural n -> Natural (n + 1)
51− >
46+ >
5247 > -- foo :: Set '[Natural 0, Natural 1, Natural 3]
5348 > foo = asSet $ Ext (S Z) (Ext (S (S (S Z))) (Ext Z Empty))
5449 >
@@ -63,15 +58,15 @@ description:
6358license: BSD3
6459license-file: LICENSE
6560category: Type System, Data Structures
66−copyright: 2013-18 University of Kent
61+copyright: 2013-16 University of Cambridge
6762author: Dominic Orchard
6863maintainer: Dominic Orchard
6964stability: experimental
7065build-type: Simple
7166cabal-version: >= 1.6
72−tested-with: GHC >= 8.2.2
67+tested-with: GHC == 7.10.3
7368
74−extra-source-files: example.hs, example2.hs, changelog.md
69+extra-source-files: example.hs
7570
7671
7772source-repository head
@@ -80,11 +75,10 @@ source-repository head
8075
8176library
8277 hs-source-dirs: src
83− other-extensions: TypeInType
8478
8579
8680 exposed-modules: Data.Type.Set
8781 Data.Type.Map
88−
82+
8983 build-depends: base < 5,
90− ghc-prim
84+ ghc-prim