@@ -2,18 +2,23 @@
2The implementation is similar to that shown in the paper.
2The implementation is similar to that shown in the paper.
3 "Embedding effect systems in Haskell" Orchard, Petricek 2014 -}
3 "Embedding effect systems in Haskell" Orchard, Petricek 2014 -}
5−{-# LANGUAGE TypeOperators, PolyKinds, DataKinds, KindSignatures,
5+{-# LANGUAGE TypeOperators, PolyKinds, DataKinds, KindSignatures,
6− TypeFamilies, UndecidableInstances, MultiParamTypeClasses,
6+ TypeFamilies, UndecidableInstances, MultiParamTypeClasses,
7− FlexibleInstances, GADTs, FlexibleContexts, ScopedTypeVariables, ConstraintKinds #-}
7+ FlexibleInstances, GADTs, FlexibleContexts, ScopedTypeVariables,
8−
8+ ConstraintKinds, IncoherentInstances #-}
9−module Data.Type.Map (Mapping(..), Union, Unionable, union, Var(..), Map(..),
10+module Data.Type.Map (Mapping(..), Union, Unionable, union, Var(..), Map(..),
10− Combine, Combinable(..), Cmp,
11+ Combine, Combinable(..), Cmp,
11− Lookup, Member, (:\)) where
13+ Lookup, Member, (:\), Split, split,
14+ IsMember, lookp, Updatable, update,
16+ Submap, submap) where
13import GHC.TypeLits
18import GHC.TypeLits
14import Data.Type.Bool
19import Data.Type.Bool
15import Data.Type.Equality
20import Data.Type.Equality
16−import Data.Type.Set hiding (Set(..), Nub,Union,Nubable,Sortable,Unionable,append,union,quicksort,nub)
21+import Data.Type.Set (Cmp, Proxy(..), Flag(..), Sort, Filter, (:++))
18{- Throughout, type variables
23{- Throughout, type variables
19 'k' ranges over "keys"
24 'k' ranges over "keys"
@@ -22,7 +27,7 @@ import Data.Type.Set hiding (Set(..), Nub,Union,Nubable,Sortable,Unionable,appen
22 'm', 'n' range over "maps" -}
27 'm', 'n' range over "maps" -}
24-- Mappings
29-- Mappings
25−infixr 4 :->
30+infixr 4 :->
26{-| A key-value pair -}
31{-| A key-value pair -}
27data Mapping k v = k :-> v
32data Mapping k v = k :-> v
@@ -41,17 +46,17 @@ type family Combine (a :: v) (b :: v) :: v
42{-| Delete elements from a map by key -}
47{-| Delete elements from a map by key -}
43type family (m :: [Mapping k v]) :\ (c :: k) :: [Mapping k v] where
48type family (m :: [Mapping k v]) :\ (c :: k) :: [Mapping k v] where
44− '[] :\ k = '[]
49+ '[] :\ k = '[]
45− ((k :-> v) ': m) :\ k = m :\ k
50+ ((k :-> v) ': m) :\ k = m :\ k
46− (kvp ': m) :\ k = kvp ': (m :\ k)
51+ (kvp ': m) :\ k = kvp ': (m :\ k)
48−{-| Lookup elements from a map -}
53+{-| Type-level lookup of elements from a map -}
49type family Lookup (m :: [Mapping k v]) (c :: k) :: Maybe v where
54type family Lookup (m :: [Mapping k v]) (c :: k) :: Maybe v where
50 Lookup '[] k = Nothing
55 Lookup '[] k = Nothing
51 Lookup ((k :-> v) ': m) k = Just v
56 Lookup ((k :-> v) ': m) k = Just v
52 Lookup (kvp ': m) k = Lookup m k
57 Lookup (kvp ': m) k = Lookup m k
54−{-| Membership test -}
59+{-| Membership test as type function -}
55type family Member (c :: k) (m :: [Mapping k v]) :: Bool where
60type family Member (c :: k) (m :: [Mapping k v]) :: Bool where
56 Member k '[] = False
61 Member k '[] = False
57 Member k ((k :-> v) ': m) = True
62 Member k ((k :-> v) ': m) = True
@@ -61,7 +66,7 @@ type family Member (c :: k) (m :: [Mapping k v]) :: Bool where
61-- Value-level map with a type-level representation
66-- Value-level map with a type-level representation
63{-| Pair a symbol (representing a variable) with a type -}
68{-| Pair a symbol (representing a variable) with a type -}
64−data Var (k :: Symbol) = Var
69+data Var (k :: Symbol) = Var
66instance KnownSymbol k => Show (Var k) where
71instance KnownSymbol k => Show (Var k) where
67 show = symbolVal
72 show = symbolVal
@@ -71,11 +76,52 @@ data Map (n :: [Mapping Symbol *]) where
71 Empty :: Map '[]
76 Empty :: Map '[]
72 Ext :: Var k -> v -> Map m -> Map ((k :-> v) ': m)
77 Ext :: Var k -> v -> Map m -> Map ((k :-> v) ': m)
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
84+instance {-# OVERLAPS #-} IsMember v t ((v ':-> t) ': m) where
85+ lookp _ (Ext _ x _) = x
87+instance {-# OVERLAPPABLE #-} IsMember v t m => IsMember v t (x ': m) where
88+ lookp v (Ext _ _ m) = lookp v m
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
97+instance {-# OVERLAPS #-} Updatable v t ((v ':-> s) ': m) ((v ':-> t) ': m) where
98+ update (Ext v _ m) _ x = Ext v x m
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)
103+-- instance Updatable v t '[] '[v ':-> t] where
104+-- update Empty v x = Ext v x Empty
106+instance Updatable v t s ((v ':-> t) ': s) where
107+ update xs v x = Ext v x xs
110+{-| Predicate to check if in normalised map form -}
111+type IsMap s = (s ~ Nub (Sort s))
113+{-| At the type level, normalise the list form to the map form -}
114+type AsMap s = Nub (Sort s)
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)
74instance Show (Map '[]) where
120instance Show (Map '[]) where
75 show Empty = "{}"
121 show Empty = "{}"
77instance (KnownSymbol k, Show v, Show' (Map s)) => Show (Map ((k :-> v) ': s)) where
123instance (KnownSymbol k, Show v, Show' (Map s)) => Show (Map ((k :-> v) ': s)) where
78− show (Ext k v s) = "{" ++ show k ++ " :-> " ++ show v ++ (show' s) ++ "}"
124+ show (Ext k v s) = "{" ++ show k ++ " :-> " ++ show v ++ show' s ++ "}"
80class Show' t where
126class Show' t where
81 show' :: t -> String
127 show' :: t -> String
@@ -84,18 +130,31 @@ instance Show' (Map '[]) where
84instance (KnownSymbol k, Show v, Show' (Map s)) => Show' (Map ((k :-> v) ': s)) where
130instance (KnownSymbol k, Show v, Show' (Map s)) => Show' (Map ((k :-> v) ': s)) where
85 show' (Ext k v s) = ", " ++ show k ++ " :-> " ++ show v ++ (show' s)
131 show' (Ext k v s) = ", " ++ show k ++ " :-> " ++ show v ++ (show' s)
133+instance Eq (Map '[]) where
134+ Empty == Empty = True
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'
139+instance Ord (Map '[]) where
140+ compare Empty Empty = EQ
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'
87−{-| Union of two finite maps -}
145+{-| Union of two finite maps (normalising) -}
88union :: (Unionable s t) => Map s -> Map t -> Map (Union s t)
146union :: (Unionable s t) => Map s -> Map t -> Map (Union s t)
89union s t = nub (quicksort (append s t))
147union s t = nub (quicksort (append s t))
91type Unionable s t = (Nubable (Sort (s :++ t)), Sortable (s :++ t))
149type Unionable s t = (Nubable (Sort (s :++ t)), Sortable (s :++ t))
151+{-| Append of two finite maps (non normalising) -}
93append :: Map s -> Map t -> Map (s :++ t)
152append :: Map s -> Map t -> Map (s :++ t)
94append Empty x = x
153append Empty x = x
95append (Ext k v xs) ys = Ext k v (append xs ys)
154append (Ext k v xs) ys = Ext k v (append xs ys)
97type instance Cmp (k :: Symbol) (k' :: Symbol) = CmpSymbol k k'
156type instance Cmp (k :: Symbol) (k' :: Symbol) = CmpSymbol k k'
98−type instance Cmp (k :-> v) (k' :-> v) = CmpSymbol k k'
157+type instance Cmp (k :-> v) (k' :-> v') = CmpSymbol k k'
100{-| Value-level quick sort that respects the type-level ordering -}
159{-| Value-level quick sort that respects the type-level ordering -}
101class Sortable xs where
160class Sortable xs where
@@ -104,11 +163,15 @@ class Sortable xs where
104instance Sortable '[] where
163instance Sortable '[] where
105 quicksort Empty = Empty
164 quicksort Empty = Empty
107−instance (Sortable (Filter FMin (k :-> v) xs),
166+instance (Sortable (Filter FMin (k :-> v) xs)
167+ , Sortable (Filter FMax (k :-> v) xs)
168+ , FilterV FMin k v xs
108− Sortable (Filter FMax (k :-> v) xs), FilterV FMin k v xs, FilterV FMax k v xs) => Sortable ((k :-> v) ': xs) where
169+ , FilterV FMax k v xs) => Sortable ((k :-> v) ': xs) where
170+ quicksort (Ext k v xs) =
109− quicksort (Ext k v xs) = ((quicksort (less k v xs)) `append` (Ext k v Empty)) `append` (quicksort (more k v xs))
171+ quicksort (less k v xs) `append` Ext k v Empty `append` quicksort (more k v xs)
110− where less = filterV (Proxy::(Proxy FMin))
173+ less = filterV (Proxy::(Proxy FMin))
111− more = filterV (Proxy::(Proxy FMax))
174+ more = filterV (Proxy::(Proxy FMax))
113{- Filter out the elements less-than or greater-than-or-equal to the pivot -}
176{- Filter out the elements less-than or greater-than-or-equal to the pivot -}
114class FilterV (f::Flag) k v xs where
177class FilterV (f::Flag) k v xs where
@@ -117,13 +180,19 @@ class FilterV (f::Flag) k v xs where
117instance FilterV f k v '[] where
180instance FilterV f k v '[] where
118 filterV _ k v Empty = Empty
181 filterV _ k v Empty = Empty
120−instance (Conder ((Cmp x (k :-> v)) == LT), FilterV FMin k v xs) => FilterV FMin k v (x ': xs) where
183+instance (Conder (Cmp x (k :-> v) == LT), FilterV FMin k v xs) => FilterV FMin k v (x ': xs) where
121− filterV f@Proxy k v (Ext k' v' xs) = cond (Proxy::(Proxy ((Cmp x (k :-> v)) == LT)))
184+ filterV f@Proxy k v (Ext k' v' xs) =
185+ cond (Proxy::(Proxy (Cmp x (k :-> v) == LT)))
122− (Ext k' v' (filterV f k v xs)) (filterV f k v xs)
186+ (Ext k' v' (filterV f k v xs))
124−instance (Conder (((Cmp x (k :-> v)) == GT) || ((Cmp x (k :-> v)) == EQ)), FilterV FMax k v xs) => FilterV FMax k v (x ': xs) where
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) =
125− filterV f@Proxy k v (Ext k' v' xs) = cond (Proxy::(Proxy (((Cmp x (k :-> v)) == GT) || ((Cmp x (k :-> v)) == EQ))))
193+ cond (Proxy::(Proxy ((Cmp x (k :-> v) == GT) || (Cmp x (k :-> v) == EQ))))
126− (Ext k' v' (filterV f k v xs)) (filterV f k v xs)
194+ (Ext k' v' (filterV f k v xs))
128class Combinable t t' where
197class Combinable t t' where
129 combine :: t -> t' -> Combine t t'
198 combine :: t -> t' -> Combine t t'
@@ -137,15 +206,17 @@ instance Nubable '[] where
137instance Nubable '[e] where
206instance Nubable '[e] where
138 nub (Ext k v Empty) = Ext k v Empty
207 nub (Ext k v Empty) = Ext k v Empty
140−instance {-# OVERLAPPING #-}
209+instance {-# OVERLAPPABLE #-}
141− (Combinable v v', Nubable ((k :-> Combine v v') ': s)) => Nubable ((k :-> v) ': (k :-> v') ': s) where
142− nub (Ext k v (Ext k' v' s)) = nub (Ext k (combine v v') s)
144−instance {-# OVERLAPPING #-}
145− (Nub (e ': f ': s) ~ (e ': Nub (f ': s)),
210+ (Nub (e ': f ': s) ~ (e ': Nub (f ': s)),
146 Nubable (f ': s)) => Nubable (e ': f ': s) where
211 Nubable (f ': s)) => Nubable (e ': f ': s) where
147 nub (Ext k v (Ext k' v' s)) = Ext k v (nub (Ext k' v' s))
212 nub (Ext k v (Ext k' v' s)) = Ext k v (nub (Ext k' v' s))
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)
149class Conder g where
220class Conder g where
150 cond :: Proxy g -> Map s -> Map t -> Map (If g s t)
221 cond :: Proxy g -> Map s -> Map t -> Map (If g s t)
@@ -155,3 +226,36 @@ instance Conder True where
155instance Conder False where
226instance Conder False where
156 cond _ s t = t
227 cond _ s t = t
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)
235+instance Split '[] '[] '[] where
236+ split Empty = (Empty, Empty)
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)
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
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
250+{-| Construct a submap 's' from a supermap 't' -}
251+class Submap s t where
252+ submap :: Map t -> Map s
254+instance Submap '[] '[] where
257+instance {-# OVERLAPPABLE #-} Submap s t => Submap s (x ': t) where
258+ submap (Ext _ _ xs) = submap xs
260+instance {-# OVERLAPS #-} Submap s t => Submap (x ': s) (x ': t) where
261+ submap (Ext k v xs) = Ext k v (submap xs)