1 % Copyright (C) 2007 David Roundy
3 % This program is free software; you can redistribute it and/or modify
4 % it under the terms of the GNU General Public License as published by
5 % the Free Software Foundation; either version 2, or (at your option)
8 % This program is distributed in the hope that it will be useful,
9 % but WITHOUT ANY WARRANTY; without even the implied warranty of
10 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 % GNU General Public License for more details.
13 % You should have received a copy of the GNU General Public License
14 % along with this program; see the file COPYING. If not, write to
15 % the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16 % Boston, MA 02110-1301, USA.
19 {-# OPTIONS_GHC -cpp -fglasgow-exts #-}
21 -- , MagicHash, TypeOperators, GADTs #-}
25 module Darcs.Ordered ( EqCheck(..), isEq, (:>)(..), (:<)(..), (:\/:)(..), (:/\:)(..),
26 FL(..), RL(..),Proof(..),
27 #ifndef GADT_WITNESSES
28 unsafeUnFL, unsafeFL, unsafeRL, unsafeUnRL,
30 lengthFL, mapFL, mapFL_FL, spanFL, foldlFL, allFL,
31 splitAtFL, bunchFL, foldlRL,
32 lengthRL, isShorterThanRL, mapRL, mapRL_RL, zipWithFL,
33 unsafeMap_l2f, filterE, filterFL,
34 reverseFL, reverseRL, (+>+), (+<+),
35 nullFL, concatFL, concatRL, concatReverseFL, headRL,
36 MyEq, unsafeCompare, (=\/=), (=/\=),
38 unsafeCoerceP, unsafeCoerceP2
41 #include "impossible.h"
42 import GHC.Base (unsafeCoerce#)
44 import Darcs.Sealed ( FlippedSeal(..), flipSeal )
46 data EqCheck C(a b) where
47 IsEq :: EqCheck C(a a)
48 NotEq :: EqCheck C(a b)
50 instance Eq (EqCheck C(a b)) where
55 isEq :: EqCheck C(a b) -> Bool
59 instance Show (EqCheck C(a b)) where
63 data Proof a C(x y) where
64 Proof :: a -> Proof a C(x x)
66 data (a1 :> a2) C(x y) = FORALL(z) (a1 C(x z)) :> (a2 C(z y))
68 data (a1 :< a2) C(x y) = FORALL(z) (a1 C(z y)) :< (a2 C(x z))
71 data (a1 :\/: a2) C(x y) = FORALL(z) (a1 C(z x)) :\/: (a2 C(z y))
72 data (a1 :/\: a2) C(x y) = FORALL(z) (a1 C(x z)) :/\: (a2 C(y z))
74 -- Minimal definition defines any one of unsafeCompare, =\/= and =/\=.
75 unsafeCompare :: p C(a b) -> p C(c d) -> Bool
76 unsafeCompare a b = IsEq == (a =/\= unsafeCoerceP b)
77 (=\/=) :: p C(a b) -> p C(a c) -> EqCheck C(b c)
78 a =\/= b | unsafeCompare a b = unsafeCoerceP IsEq
80 (=/\=) :: p C(a c) -> p C(b c) -> EqCheck C(a b)
81 a =/\= b | IsEq == (a =\/= unsafeCoerceP b) = unsafeCoerceP IsEq
86 unsafeCoerceP :: a C(x y) -> a C(b c)
87 unsafeCoerceP = unsafeCoerce#
89 unsafeCoerceP2 :: t C(w x y z) -> t C(a b c d)
90 unsafeCoerceP2 = unsafeCoerce#
92 instance (Show2 a, Show2 b) => Show ( (a :> b) C(x y) ) where
93 showsPrec d (x :> y) = showOp2 1 ":>" d x y
95 instance (Show2 a, Show2 b) => Show2 (a :> b) where
96 showsPrec2 = showsPrec
98 instance (Show2 a, Show2 b) => Show ( (a :\/: b) C(x y) ) where
99 showsPrec d (x :\/: y) = showOp2 9 ":\\/:" d x y
101 instance (Show2 a, Show2 b) => Show2 (a :\/: b) where
102 showsPrec2 = showsPrec
104 infixr 5 :>:, :<:, +>+, +<+
107 data FL a C(x z) where
108 (:>:) :: a C(x y) -> FL a C(y z) -> FL a C(x z)
111 instance Show2 a => Show (FL a C(x z)) where
112 showsPrec _ NilFL = showString "NilFL"
113 showsPrec d (x :>: xs) = showParen (d > prec) $ showsPrec2 (prec + 1) x .
114 showString " :>: " . showsPrec (prec + 1) xs
117 instance Show2 a => Show2 (FL a) where
118 showsPrec2 = showsPrec
121 data RL a C(x z) where
122 (:<:) :: a C(y z) -> RL a C(x y) -> RL a C(x z)
125 nullFL :: FL a C(x z) -> Bool
129 nullRL :: RL a C(x z) -> Bool
133 filterFL :: (FORALL(x y) p C(x y) -> EqCheck C(x y)) -> FL p C(w z) -> FL p C(w z)
134 filterFL _ NilFL = NilFL
135 filterFL f (x:>:xs) | IsEq <- f x = filterFL f xs
136 | otherwise = x :>: filterFL f xs
138 filterE :: (a -> EqCheck C(x y)) -> [a] -> [Proof a C(x y)]
141 | IsEq <- p x = Proof x : filterE p xs
142 | otherwise = filterE p xs
144 (+>+) :: FL a C(x y) -> FL a C(y z) -> FL a C(x z)
146 (x:>:xs) +>+ ys = x :>: xs +>+ ys
148 (+<+) :: RL a C(y z) -> RL a C(x y) -> RL a C(x z)
150 (x:<:xs) +<+ ys = x :<: xs +<+ ys
152 reverseFL :: FL a C(x z) -> RL a C(x z)
153 reverseFL xs = r NilRL xs
154 where r :: RL a C(l m) -> FL a C(m o) -> RL a C(l o)
156 r ls (a:>:as) = r (a:<:ls) as
158 reverseRL :: RL a C(x z) -> FL a C(x z)
159 reverseRL xs = r NilFL xs -- r (xs :> NilFL)
160 where r :: FL a C(m o) -> RL a C(l m) -> FL a C(l o)
162 r ls (a:<:as) = r (a:>:ls) as
164 concatFL :: FL (FL a) C(x z) -> FL a C(x z)
165 concatFL NilFL = NilFL
166 concatFL (a:>:as) = a +>+ concatFL as
168 concatRL :: RL (RL a) C(x z) -> RL a C(x z)
169 concatRL NilRL = NilRL
170 concatRL (a:<:as) = a +<+ concatRL as
172 spanFL :: (FORALL(w y) a C(w y) -> Bool) -> FL a C(x z) -> (FL a :> FL a) C(x z)
173 spanFL f (x:>:xs) | f x = case spanFL f xs of
174 ys :> zs -> (x:>:ys) :> zs
175 spanFL _ xs = NilFL :> xs
177 splitAtFL :: Int -> FL a C(x z) -> (FL a :> FL a) C(x z)
178 splitAtFL 0 xs = NilFL :> xs
179 splitAtFL _ NilFL = NilFL :> NilFL
180 splitAtFL n (x:>:xs) = case splitAtFL (n-1) xs of
181 (xs':>xs'') -> (x:>:xs' :> xs'')
183 -- 'bunchFL n' groups patches into batches of n, except that it always puts
184 -- the first patch in its own group, this being a recognition that the
185 -- first patch is often *very* large.
187 bunchFL :: Int -> FL a C(x y) -> FL (FL a) C(x y)
188 bunchFL _ NilFL = NilFL
189 bunchFL n (x:>:xs) = (x :>: NilFL) :>: bFL xs
190 where bFL :: FL a C(x y) -> FL (FL a) C(x y)
192 bFL bs = case splitAtFL n bs of
193 a :> b -> a :>: bFL b
196 allFL :: (FORALL(x y) a C(x y) -> Bool) -> FL a C(w z) -> Bool
197 allFL f xs = and $ mapFL f xs
199 foldlFL :: (FORALL(w y) a -> b C(w y) -> a) -> a -> FL b C(x z) -> a
200 foldlFL _ x NilFL = x
201 foldlFL f x (y:>:ys) = foldlFL f (f x y) ys
203 foldlRL :: (FORALL(w y) a -> b C(w y) -> a) -> a -> RL b C(x z) -> a
204 foldlRL _ x NilRL = x
205 foldlRL f x (y:<:ys) = foldlRL f (f x y) ys
207 mapFL_FL :: (FORALL(w y) a C(w y) -> b C(w y)) -> FL a C(x z) -> FL b C(x z)
208 mapFL_FL _ NilFL = NilFL
209 mapFL_FL f (a:>:as) = f a :>: mapFL_FL f as
211 zipWithFL :: (FORALL(x y) a -> p C(x y) -> q C(x y))
212 -> [a] -> FL p C(w z) -> FL q C(w z)
213 zipWithFL f (x:xs) (y :>: ys) = f x y :>: zipWithFL f xs ys
214 zipWithFL _ _ NilFL = NilFL
215 zipWithFL _ [] (_:>:_) = bug "zipWithFL called with too short a list"
217 mapRL_RL :: (FORALL(w y) a C(w y) -> b C(w y)) -> RL a C(x z) -> RL b C(x z)
218 mapRL_RL _ NilRL = NilRL
219 mapRL_RL f (a:<:as) = f a :<: mapRL_RL f as
221 mapFL :: (FORALL(w z) a C(w z) -> b) -> FL a C(x y) -> [b]
223 mapFL f (a :>: b) = f a : mapFL f b
225 mapRL :: (FORALL(w z) a C(w z) -> b) -> RL a C(x y) -> [b]
227 mapRL f (a :<: b) = f a : mapRL f b
229 unsafeMap_l2f :: (FORALL(w z) a -> b C(w z)) -> [a] -> FL b C(x y)
230 unsafeMap_l2f _ [] = unsafeCoerceP NilFL
231 unsafeMap_l2f f (x:xs) = f x :>: unsafeMap_l2f f xs
233 lengthFL :: FL a C(x z) -> Int
235 where l :: FL a C(x z) -> Int -> Int
237 l (_:>:as) n = l as $! n+1
239 lengthRL :: RL a C(x z) -> Int
241 where l :: RL a C(x z) -> Int -> Int
243 l (_:<:as) n = l as $! n+1
245 isShorterThanRL :: RL a C(x y) -> Int -> Bool
246 isShorterThanRL _ n | n <= 0 = False
247 isShorterThanRL NilRL _ = True
248 isShorterThanRL (_:<:xs) n = isShorterThanRL xs (n-1)
250 concatReverseFL :: FL (RL a) C(x y) -> RL a C(x y)
251 concatReverseFL = concatRL . reverseFL
253 headRL :: RL a C(x y) -> FlippedSeal a C(y)
254 headRL (x:<:_) = flipSeal x
255 headRL _ = impossible
257 consRLSealed :: a C(y z) -> FlippedSeal (RL a) C(y) -> FlippedSeal (RL a) C(z)
258 consRLSealed a (FlippedSeal as) = flipSeal $ a :<: as
260 #ifndef GADT_WITNESSES
261 -- These are useful for interfacing with modules outside of
262 -- patch theory, such as Show.lhs
263 unsafeUnFL :: FL a -> [a]
264 unsafeUnFL NilFL = []
265 unsafeUnFL (a:>:as) = a : unsafeUnFL as
267 unsafeUnRL :: RL a -> [a]
268 unsafeUnRL NilRL = []
269 unsafeUnRL (a:<:as) = a : unsafeUnRL as
271 unsafeFL :: [a] -> FL a
273 unsafeFL (a:as) = a :>: unsafeFL as
275 unsafeRL :: [a] -> RL a
277 unsafeRL (a:as) = a :<: unsafeRL as