Skip to content

Commit e918f27

Browse files
committedSep 11, 2014
split off the set representation from the effect monad library (ixmonad)
0 parents  commit e918f27

File tree

3 files changed

+238
-0
lines changed

3 files changed

+238
-0
lines changed
 

‎LICENSE

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
Copyright (c) 2014, Dominic Orchard
2+
3+
All rights reserved.
4+
5+
Redistribution and use in source and binary forms, with or without
6+
modification, are permitted provided that the following conditions are met:
7+
8+
* Redistributions of source code must retain the above copyright
9+
notice, this list of conditions and the following disclaimer.
10+
11+
* Redistributions in binary form must reproduce the above
12+
copyright notice, this list of conditions and the following
13+
disclaimer in the documentation and/or other materials provided
14+
with the distribution.
15+
16+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19+
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20+
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22+
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24+
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

‎Setup.hs

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
module Main (main) where
2+
3+
import Distribution.Simple
4+
5+
main :: IO ()
6+
main = defaultMain

‎src/Data/Type/Set.hs

+206
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
{-# LANGUAGE GADTs, DataKinds, KindSignatures, TypeOperators, TypeFamilies,
2+
MultiParamTypeClasses, FlexibleInstances, PolyKinds, FlexibleContexts,
3+
UndecidableInstances, ConstraintKinds, OverlappingInstances, ScopedTypeVariables,
4+
AllowAmbiguousTypes #-}
5+
6+
module Data.Type.Set (Set(..), Union, Unionable, union, quicksort, append,
7+
Sort, Sortable, Append(..), Split(..), Cmp,
8+
Nub, Nubable(..), AsSet, asSet, IsSet, Subset(..)) where
9+
10+
import GHC.TypeLits
11+
import Data.Type.Bool
12+
import Data.Type.Equality
13+
import Data.Proxy
14+
15+
{-| Core Set definition, in terms of lists -}
16+
data Set (n :: [*]) where
17+
Empty :: Set '[]
18+
Ext :: e -> Set s -> Set (e ': s)
19+
20+
instance Show (Set '[]) where
21+
show Empty = "{}"
22+
23+
instance (Show e, Show' (Set s)) => Show (Set (e ': s)) where
24+
show (Ext e s) = "{" ++ show e ++ (show' s) ++ "}"
25+
26+
class Show' t where
27+
show' :: t -> String
28+
instance Show' (Set '[]) where
29+
show' Empty = ""
30+
instance (Show' (Set s), Show e) => Show' (Set (e ': s)) where
31+
show' (Ext e s) = ", " ++ show e ++ (show' s)
32+
33+
{-| At the type level, normalise the list form to the set form -}
34+
type AsSet s = Nub (Sort s)
35+
36+
{-| At the value level, noramlise the list form to the set form -}
37+
asSet :: (Sortable s, Nubable (Sort s)) => Set s -> Set (AsSet s)
38+
asSet x = nub (quicksort x)
39+
40+
{-| Predicate to check if in the set form -}
41+
type IsSet s = (s ~ Nub (Sort s))
42+
43+
{-| Useful properties to be able to refer to someties -}
44+
type SetProperties f = (Union f '[] ~ f, Split f '[] f,
45+
Union '[] f ~ f, Split '[] f f,
46+
Union f f ~ f, Split f f f,
47+
Unionable f '[], Unionable '[] f)
48+
49+
{-- Union --}
50+
51+
{-| Union of sets -}
52+
type Union s t = Nub (Sort (Append s t))
53+
54+
union :: (Unionable s t) => Set s -> Set t -> Set (Union s t)
55+
union s t = nub (quicksort (append s t))
56+
57+
type Unionable s t = (Sortable (Append s t), Nubable (Sort (Append s t)))
58+
59+
{-| List append (essentially set disjoint union) -}
60+
type family Append (s :: [k]) (t :: [k]) :: [k] where
61+
Append '[] t = t
62+
Append (x ': xs) ys = x ': (Append xs ys)
63+
64+
append :: Set s -> Set t -> Set (Append s t)
65+
append Empty x = x
66+
append (Ext e xs) ys = Ext e (append xs ys)
67+
68+
{-| Useful alias for append -}
69+
type (s :: [k]) :++ (t :: [k]) = Append s t
70+
71+
{-| Splitting a union a set, given the sets we want to split it into -}
72+
class Split s t st where
73+
-- where st ~ Union s t
74+
split :: Set st -> (Set s, Set t)
75+
76+
instance Split '[] '[] '[] where
77+
split Empty = (Empty, Empty)
78+
79+
instance Split s t st => Split (x ': s) (x ': t) (x ': st) where
80+
split (Ext x st) = let (s, t) = split st
81+
in (Ext x s, Ext x t)
82+
83+
instance Split s t st => Split (x ': s) t (x ': st) where
84+
split (Ext x st) = let (s, t) = split st
85+
in (Ext x s, t)
86+
87+
instance (Split s t st) => Split s (x ': t) (x ': st) where
88+
split (Ext x st) = let (s, t) = split st
89+
in (s, Ext x t)
90+
91+
92+
93+
{-| Remove duplicates from a sorted list -}
94+
type family Nub t where
95+
Nub '[] = '[]
96+
Nub '[e] = '[e]
97+
Nub (e ': e ': s) = Nub (e ': s)
98+
Nub (e ': f ': s) = e ': Nub (f ': s)
99+
100+
{-| Value-level counterpart to the type-level 'Nub'
101+
Note: the value-level case for equal types is not define here,
102+
but should be given per-application, e.g., custom 'merging' behaviour may be required -}
103+
104+
class Nubable t where
105+
nub :: Set t -> Set (Nub t)
106+
107+
instance Nubable '[] where
108+
nub Empty = Empty
109+
110+
instance Nubable '[e] where
111+
nub (Ext x Empty) = Ext x Empty
112+
113+
instance (Nub (e ': f ': s) ~ (e ': Nub (f ': s)),
114+
Nubable (f ': s)) => Nubable (e ': f ': s) where
115+
nub (Ext e (Ext f s)) = Ext e (nub (Ext f s))
116+
117+
118+
{-| Construct a subsetset 's' from a superset 't' -}
119+
class Subset s t where
120+
subset :: Set t -> Set s
121+
122+
instance Subset '[] '[] where
123+
subset xs = Empty
124+
125+
instance Subset '[] (x ': t) where
126+
subset xs = Empty
127+
128+
instance Subset s t => Subset (x ': s) (x ': t) where
129+
subset (Ext x xs) = Ext x (subset xs)
130+
131+
132+
{-| Type-level quick sort for normalising the representation of sets -}
133+
type family Sort (xs :: [k]) :: [k] where
134+
Sort '[] = '[]
135+
Sort (x ': xs) = ((Sort (Filter FMin x xs)) :++ '[x]) :++ (Sort (Filter FMax x xs))
136+
137+
data Flag = FMin | FMax
138+
139+
type family Filter (f :: Flag) (p :: k) (xs :: [k]) :: [k] where
140+
Filter f p '[] = '[]
141+
Filter FMin p (x ': xs) = If (Cmp x p == LT) (x ': (Filter FMin p xs)) (Filter FMin p xs)
142+
Filter FMax p (x ': xs) = If (Cmp x p == GT || Cmp x p == EQ) (x ': (Filter FMax p xs)) (Filter FMax p xs)
143+
144+
{-| Value-level quick sort that respects the type-level ordering -}
145+
class Sortable xs where
146+
quicksort :: Set xs -> Set (Sort xs)
147+
148+
instance Sortable '[] where
149+
quicksort Empty = Empty
150+
151+
instance (Sortable (Filter FMin p xs),
152+
Sortable (Filter FMax p xs), FilterV FMin p xs, FilterV FMax p xs) => Sortable (p ': xs) where
153+
quicksort (Ext p xs) = ((quicksort (less p xs)) `append` (Ext p Empty)) `append` (quicksort (more p xs))
154+
where less = filterV (Proxy::(Proxy FMin))
155+
more = filterV (Proxy::(Proxy FMax))
156+
157+
{- Filter out the elements less-than or greater-than-or-equal to the pivot -}
158+
class FilterV (f::Flag) p xs where
159+
filterV :: Proxy f -> p -> Set xs -> Set (Filter f p xs)
160+
161+
instance FilterV f p '[] where
162+
filterV _ p Empty = Empty
163+
164+
instance (Conder ((Cmp x p) == LT), FilterV FMin p xs) => FilterV FMin p (x ': xs) where
165+
filterV f@Proxy p (Ext x xs) = cond (Proxy::(Proxy ((Cmp x p) == LT)))
166+
(Ext x (filterV f p xs)) (filterV f p xs)
167+
168+
instance (Conder (((Cmp x p) == GT) || ((Cmp x p) == EQ)), FilterV FMax p xs) => FilterV FMax p (x ': xs) where
169+
filterV f@Proxy p (Ext x xs) = cond (Proxy::(Proxy (((Cmp x p) == GT) || ((Cmp x p) == EQ))))
170+
(Ext x (filterV f p xs)) (filterV f p xs)
171+
172+
class Conder g where
173+
cond :: Proxy g -> Set s -> Set t -> Set (If g s t)
174+
175+
instance Conder True where
176+
cond _ s t = s
177+
178+
instance Conder False where
179+
cond _ s t = t
180+
181+
{-| Open-family for the ordering operation in the sort -}
182+
183+
type family Cmp (a :: k) (b :: k) :: Ordering
184+
185+
{-| Pair a symbol (represetning a variable) with a type -}
186+
infixl 2 :->
187+
data (k :: Symbol) :-> (v :: *) = (Var k) :-> v
188+
189+
data Var (k :: Symbol) where Var :: Var k
190+
{-| Some special defaults for some common names -}
191+
X :: Var "x"
192+
Y :: Var "y"
193+
Z :: Var "z"
194+
195+
196+
instance (Show (Var k), Show v) => Show (k :-> v) where
197+
show (k :-> v) = "(" ++ show k ++ " :-> " ++ show v ++ ")"
198+
instance Show (Var "x") where
199+
show _ = "x"
200+
instance Show (Var "y") where
201+
show _ = "y"
202+
instance Show (Var "z") where
203+
show _ = "z"
204+
205+
{-| Symbol comparison -}
206+
type instance Cmp (v :-> a) (u :-> b) = CmpSymbol v u

0 commit comments

Comments
 (0)
Please sign in to comment.