1
{-# LANGUAGE DeriveDataTypeable, CPP #-}
2
{-# LANGUAGE DeriveDataTypeable #-}
3
{-# LANGUAGE DeriveFoldable #-}
4
{-# LANGUAGE DeriveFunctor #-}
5
{-# LANGUAGE DeriveTraversable #-}
2
7
module Agda.Utils.Permutation where
9
import Prelude hiding (drop)
11
import Data.List hiding (drop)
12
import qualified Data.List as List
15
import Data.Foldable (Foldable)
16
import Data.Traversable (Traversable)
4
17
import Data.Typeable (Typeable)
6
19
import Agda.Utils.Size
20
import Agda.Utils.List ((!!!))
22
#include "../undefined.h"
7
23
import Agda.Utils.Impossible
9
#include "../undefined.h"
25
-- | Partial permutations. Examples:
27
-- @permute [1,2,0] [x0,x1,x2] = [x1,x2,x0]@ (proper permutation).
29
-- @permute [1,0] [x0,x1,x2] = [x1,x0]@ (partial permuation).
31
-- @permute [1,0,1,2] [x0,x1,x2] = [x1,x0,x1,x2]@ (not a permutation because not invertible).
12
33
-- Agda typing would be:
13
34
-- @Perm : {m : Nat}(n : Nat) -> Vec (Fin n) m -> Permutation@
36
56
-- @permute (Perm {m} n is) : Vec A m -> Vec A n@
37
57
permute :: Permutation -> [a] -> [a]
38
permute (Perm _ is) xs = map (xs !!!) is
58
permute (Perm _ is) xs = map (xs !!!!) is
40
[] !!! _ = __IMPOSSIBLE__
42
(x:xs) !!! n = xs !!! (n - 1)
60
xs !!!! n = fromMaybe __IMPOSSIBLE__ (xs !!! n)
62
-- | Identity permutation.
44
63
idP :: Int -> Permutation
45
64
idP n = Perm n [0..n - 1]
66
-- | Restrict a permutation to work on @n@ elements, discarding picks @>=n@.
47
67
takeP :: Int -> Permutation -> Permutation
48
68
takeP n (Perm m xs) = Perm n $ filter (< n) xs
70
-- | Pick the elements that are not picked by the permutation.
71
droppedP :: Permutation -> Permutation
72
droppedP (Perm n xs) = Perm n $ [0..n-1] \\ xs
50
74
-- | @liftP k@ takes a @Perm {m} n@ to a @Perm {m+k} (n+k)@.
51
75
-- Analogous to 'Agda.TypeChecking.Substitution.liftS',
52
76
-- but Permutations operate on de Bruijn LEVELS, not indices.
130
154
xs = [ x | (x, []) <- g ]
131
155
remove x g = [ (y, filter (/= x) ys) | (y, ys) <- g, x /= y ]
157
-- * Drop (apply) and undrop (abstract)
159
-- | Delayed dropping which allows undropping.
161
{ dropN :: Int -- ^ Non-negative number of things to drop.
162
, dropFrom :: a -- ^ Where to drop from.
164
deriving (Eq, Ord, Show, Typeable, Functor, Foldable, Traversable)
166
-- | Things that support delayed dropping.
169
doDrop :: Drop a -> a -- ^ Perform the dropping.
171
dropMore :: Int -> Drop a -> Drop a -- ^ Drop more.
172
dropMore n (Drop m xs) = Drop (m + n) xs
174
unDrop :: Int -> Drop a -> Drop a -- ^ Pick up dropped stuff.
176
| n <= m = Drop (m - n) xs
177
| otherwise = __IMPOSSIBLE__
179
instance DoDrop [a] where
180
doDrop (Drop m xs) = List.drop m xs
182
instance DoDrop Permutation where
183
doDrop (Drop k (Perm n xs)) =
184
Perm (n + m) $ [0..m-1] ++ map (+ m) (List.drop k xs)
186
unDrop m = dropMore (-m) -- allow picking up more than dropped