{-# LANGUAGE PatternGuards #-}
module Unbound.Generics.PermM (
Perm(..), permValid, single, compose, apply, support, isid, join, empty, restrict, mkPerm
) where
import Prelude (Eq(..), Show(..), (.), ($), Monad(return), Ord(..), Maybe(..), otherwise, (&&), Bool(..), id, uncurry, Functor(..))
import Data.Monoid hiding ((<>))
import Data.List
import Data.Map (Map)
import Data.Semigroup as Sem
import qualified Data.Map as M
import qualified Data.Set as S
import Control.Arrow ((&&&))
import Control.Monad ((>=>))
newtype Perm a = Perm (Map a a)
permValid :: Ord a => Perm a -> Bool
permValid :: forall a. Ord a => Perm a -> Bool
permValid (Perm Map a a
p) = ((a, a) -> Bool) -> [(a, a)] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (\(a
_,a
v) -> a -> Map a a -> Bool
forall k a. Ord k => k -> Map k a -> Bool
M.member a
v Map a a
p) (Map a a -> [(a, a)]
forall k a. Map k a -> [(k, a)]
M.assocs Map a a
p)
instance Ord a => Eq (Perm a) where
(Perm Map a a
p1) == :: Perm a -> Perm a -> Bool
== (Perm Map a a
p2) =
(a -> Bool) -> [a] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (\a
x -> a -> a -> Map a a -> a
forall k a. Ord k => a -> k -> Map k a -> a
M.findWithDefault a
x a
x Map a a
p1 a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a -> a -> Map a a -> a
forall k a. Ord k => a -> k -> Map k a -> a
M.findWithDefault a
x a
x Map a a
p2) (Map a a -> [a]
forall k a. Map k a -> [k]
M.keys Map a a
p1) Bool -> Bool -> Bool
&&
(a -> Bool) -> [a] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (\a
x -> a -> a -> Map a a -> a
forall k a. Ord k => a -> k -> Map k a -> a
M.findWithDefault a
x a
x Map a a
p1 a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a -> a -> Map a a -> a
forall k a. Ord k => a -> k -> Map k a -> a
M.findWithDefault a
x a
x Map a a
p2) (Map a a -> [a]
forall k a. Map k a -> [k]
M.keys Map a a
p2)
instance Show a => Show (Perm a) where
show :: Perm a -> String
show (Perm Map a a
p) = Map a a -> String
forall a. Show a => a -> String
show Map a a
p
apply :: Ord a => Perm a -> a -> a
apply :: forall a. Ord a => Perm a -> a -> a
apply (Perm Map a a
p) a
x = a -> a -> Map a a -> a
forall k a. Ord k => a -> k -> Map k a -> a
M.findWithDefault a
x a
x Map a a
p
single :: Ord a => a -> a -> Perm a
single :: forall a. Ord a => a -> a -> Perm a
single a
x a
y = if a
x a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
y then Map a a -> Perm a
forall a. Map a a -> Perm a
Perm Map a a
forall k a. Map k a
M.empty else
Map a a -> Perm a
forall a. Map a a -> Perm a
Perm (a -> a -> Map a a -> Map a a
forall k a. Ord k => k -> a -> Map k a -> Map k a
M.insert a
x a
y (a -> a -> Map a a -> Map a a
forall k a. Ord k => k -> a -> Map k a -> Map k a
M.insert a
y a
x Map a a
forall k a. Map k a
M.empty))
empty :: Perm a
empty :: forall a. Perm a
empty = Map a a -> Perm a
forall a. Map a a -> Perm a
Perm Map a a
forall k a. Map k a
M.empty
compose :: Ord a => Perm a -> Perm a -> Perm a
compose :: forall a. Ord a => Perm a -> Perm a -> Perm a
compose (Perm Map a a
b) (Perm Map a a
a) =
Map a a -> Perm a
forall a. Map a a -> Perm a
Perm ([(a, a)] -> Map a a
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList ([ (a
x,a -> a -> Map a a -> a
forall k a. Ord k => a -> k -> Map k a -> a
M.findWithDefault a
y a
y Map a a
b) | (a
x,a
y) <- Map a a -> [(a, a)]
forall k a. Map k a -> [(k, a)]
M.toList Map a a
a]
[(a, a)] -> [(a, a)] -> [(a, a)]
forall a. [a] -> [a] -> [a]
++ [ (a
x, a -> a -> Map a a -> a
forall k a. Ord k => a -> k -> Map k a -> a
M.findWithDefault a
x a
x Map a a
b) | a
x <- Map a a -> [a]
forall k a. Map k a -> [k]
M.keys Map a a
b, a -> Map a a -> Bool
forall k a. Ord k => k -> Map k a -> Bool
M.notMember a
x Map a a
a]))
instance Ord a => Sem.Semigroup (Perm a) where
<> :: Perm a -> Perm a -> Perm a
(<>) = Perm a -> Perm a -> Perm a
forall a. Ord a => Perm a -> Perm a -> Perm a
compose
instance Ord a => Monoid (Perm a) where
mempty :: Perm a
mempty = Perm a
forall a. Perm a
empty
mappend :: Perm a -> Perm a -> Perm a
mappend = Perm a -> Perm a -> Perm a
forall a. Semigroup a => a -> a -> a
(<>)
isid :: Ord a => Perm a -> Bool
isid :: forall a. Ord a => Perm a -> Bool
isid (Perm Map a a
p) =
(a -> a -> Bool -> Bool) -> Bool -> Map a a -> Bool
forall k a b. (k -> a -> b -> b) -> b -> Map k a -> b
M.foldrWithKey (\ a
a a
b Bool
r -> Bool
r Bool -> Bool -> Bool
&& a
a a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
b) Bool
True Map a a
p
join :: Ord a => Perm a -> Perm a -> Maybe (Perm a)
join :: forall a. Ord a => Perm a -> Perm a -> Maybe (Perm a)
join (Perm Map a a
p1) (Perm Map a a
p2) =
let overlap :: Map a Bool
overlap = (a -> a -> Bool) -> Map a a -> Map a a -> Map a Bool
forall k a b c.
Ord k =>
(a -> b -> c) -> Map k a -> Map k b -> Map k c
M.intersectionWith a -> a -> Bool
forall a. Eq a => a -> a -> Bool
(==) Map a a
p1 Map a a
p2 in
if (Bool -> Bool -> Bool) -> Bool -> Map a Bool -> Bool
forall a b k. (a -> b -> b) -> b -> Map k a -> b
M.foldr Bool -> Bool -> Bool
(&&) Bool
True Map a Bool
overlap then
Perm a -> Maybe (Perm a)
forall a. a -> Maybe a
Just (Map a a -> Perm a
forall a. Map a a -> Perm a
Perm (Map a a -> Map a a -> Map a a
forall k a. Ord k => Map k a -> Map k a -> Map k a
M.union Map a a
p1 Map a a
p2))
else Maybe (Perm a)
forall a. Maybe a
Nothing
support :: Ord a => Perm a -> [a]
support :: forall a. Ord a => Perm a -> [a]
support (Perm Map a a
p) = [ a
x | a
x <- Map a a -> [a]
forall k a. Map k a -> [k]
M.keys Map a a
p, a -> a -> Map a a -> a
forall k a. Ord k => a -> k -> Map k a -> a
M.findWithDefault a
x a
x Map a a
p a -> a -> Bool
forall a. Eq a => a -> a -> Bool
/= a
x]
restrict :: Ord a => Perm a -> [a] -> Perm a
restrict :: forall a. Ord a => Perm a -> [a] -> Perm a
restrict (Perm Map a a
p) [a]
l = Map a a -> Perm a
forall a. Map a a -> Perm a
Perm ((Map a a -> a -> Map a a) -> Map a a -> [a] -> Map a a
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (\Map a a
p' a
k -> a -> Map a a -> Map a a
forall k a. Ord k => k -> Map k a -> Map k a
M.delete a
k Map a a
p') Map a a
p [a]
l)
data PartialPerm a = PP (M.Map a a) (M.Map a a)
deriving Int -> PartialPerm a -> ShowS
[PartialPerm a] -> ShowS
PartialPerm a -> String
(Int -> PartialPerm a -> ShowS)
-> (PartialPerm a -> String)
-> ([PartialPerm a] -> ShowS)
-> Show (PartialPerm a)
forall a. Show a => Int -> PartialPerm a -> ShowS
forall a. Show a => [PartialPerm a] -> ShowS
forall a. Show a => PartialPerm a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall a. Show a => Int -> PartialPerm a -> ShowS
showsPrec :: Int -> PartialPerm a -> ShowS
$cshow :: forall a. Show a => PartialPerm a -> String
show :: PartialPerm a -> String
$cshowList :: forall a. Show a => [PartialPerm a] -> ShowS
showList :: [PartialPerm a] -> ShowS
Show
emptyPP :: PartialPerm a
emptyPP :: forall a. PartialPerm a
emptyPP = Map a a -> Map a a -> PartialPerm a
forall a. Map a a -> Map a a -> PartialPerm a
PP Map a a
forall k a. Map k a
M.empty Map a a
forall k a. Map k a
M.empty
extendPP :: Ord a => a -> a -> PartialPerm a -> Maybe (PartialPerm a)
extendPP :: forall a. Ord a => a -> a -> PartialPerm a -> Maybe (PartialPerm a)
extendPP a
x a
y pp :: PartialPerm a
pp@(PP Map a a
mfwd Map a a
mrev)
| Just a
y' <- a -> Map a a -> Maybe a
forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup a
x Map a a
mfwd = if a
y a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
y' then PartialPerm a -> Maybe (PartialPerm a)
forall a. a -> Maybe a
Just PartialPerm a
pp
else Maybe (PartialPerm a)
forall a. Maybe a
Nothing
| Just a
x' <- a -> Map a a -> Maybe a
forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup a
y Map a a
mrev = if a
x a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
x' then PartialPerm a -> Maybe (PartialPerm a)
forall a. a -> Maybe a
Just PartialPerm a
pp
else Maybe (PartialPerm a)
forall a. Maybe a
Nothing
| Bool
otherwise = PartialPerm a -> Maybe (PartialPerm a)
forall a. a -> Maybe a
Just (PartialPerm a -> Maybe (PartialPerm a))
-> PartialPerm a -> Maybe (PartialPerm a)
forall a b. (a -> b) -> a -> b
$ Map a a -> Map a a -> PartialPerm a
forall a. Map a a -> Map a a -> PartialPerm a
PP (a -> a -> Map a a -> Map a a
forall k a. Ord k => k -> a -> Map k a -> Map k a
M.insert a
x a
y Map a a
mfwd) (a -> a -> Map a a -> Map a a
forall k a. Ord k => k -> a -> Map k a -> Map k a
M.insert a
y a
x Map a a
mrev)
ppToPerm :: Ord a => PartialPerm a -> Perm a
ppToPerm :: forall a. Ord a => PartialPerm a -> Perm a
ppToPerm (PP Map a a
mfwd Map a a
mrev) = Map a a -> Perm a
forall a. Map a a -> Perm a
Perm (Map a a -> Perm a) -> Map a a -> Perm a
forall a b. (a -> b) -> a -> b
$ ((a, a) -> Map a a -> Map a a) -> Map a a -> [(a, a)] -> Map a a
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr ((a -> a -> Map a a -> Map a a) -> (a, a) -> Map a a -> Map a a
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry a -> a -> Map a a -> Map a a
forall k a. Ord k => k -> a -> Map k a -> Map k a
M.insert) Map a a
mfwd
((a -> (a, a)) -> [a] -> [(a, a)]
forall a b. (a -> b) -> [a] -> [b]
map (a -> a
findEnd (a -> a) -> (a -> a) -> a -> (a, a)
forall b c c'. (b -> c) -> (b -> c') -> b -> (c, c')
forall (a :: * -> * -> *) b c c'.
Arrow a =>
a b c -> a b c' -> a b (c, c')
&&& a -> a
forall a. a -> a
id) [a]
chainStarts)
where chainStarts :: [a]
chainStarts = Set a -> [a]
forall a. Set a -> [a]
S.toList (Map a a -> Set a
forall k a. Map k a -> Set k
M.keysSet Map a a
mfwd Set a -> Set a -> Set a
forall a. Ord a => Set a -> Set a -> Set a
`S.difference` Map a a -> Set a
forall k a. Map k a -> Set k
M.keysSet Map a a
mrev)
findEnd :: a -> a
findEnd a
x = case a -> Map a a -> Maybe a
forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup a
x Map a a
mfwd of
Maybe a
Nothing -> a
x
Just a
x' -> a -> a
findEnd a
x'
mkPerm :: Ord a => [a] -> [a] -> Maybe (Perm a)
mkPerm :: forall a. Ord a => [a] -> [a] -> Maybe (Perm a)
mkPerm [a]
xs [a]
ys
| [a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
xs Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= [a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
ys = Maybe (Perm a)
forall a. Maybe a
Nothing
| Bool
otherwise =
(PartialPerm a -> Perm a)
-> Maybe (PartialPerm a) -> Maybe (Perm a)
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap PartialPerm a -> Perm a
forall a. Ord a => PartialPerm a -> Perm a
ppToPerm (Maybe (PartialPerm a) -> Maybe (Perm a))
-> ([PartialPerm a -> Maybe (PartialPerm a)]
-> Maybe (PartialPerm a))
-> [PartialPerm a -> Maybe (PartialPerm a)]
-> Maybe (Perm a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((PartialPerm a -> Maybe (PartialPerm a))
-> PartialPerm a -> Maybe (PartialPerm a)
forall a b. (a -> b) -> a -> b
$PartialPerm a
forall a. PartialPerm a
emptyPP) ((PartialPerm a -> Maybe (PartialPerm a)) -> Maybe (PartialPerm a))
-> ([PartialPerm a -> Maybe (PartialPerm a)]
-> PartialPerm a -> Maybe (PartialPerm a))
-> [PartialPerm a -> Maybe (PartialPerm a)]
-> Maybe (PartialPerm a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((PartialPerm a -> Maybe (PartialPerm a))
-> (PartialPerm a -> Maybe (PartialPerm a))
-> PartialPerm a
-> Maybe (PartialPerm a))
-> (PartialPerm a -> Maybe (PartialPerm a))
-> [PartialPerm a -> Maybe (PartialPerm a)]
-> PartialPerm a
-> Maybe (PartialPerm a)
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (PartialPerm a -> Maybe (PartialPerm a))
-> (PartialPerm a -> Maybe (PartialPerm a))
-> PartialPerm a
-> Maybe (PartialPerm a)
forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
(>=>) PartialPerm a -> Maybe (PartialPerm a)
forall a. a -> Maybe a
forall (m :: * -> *) a. Monad m => a -> m a
return ([PartialPerm a -> Maybe (PartialPerm a)] -> Maybe (Perm a))
-> [PartialPerm a -> Maybe (PartialPerm a)] -> Maybe (Perm a)
forall a b. (a -> b) -> a -> b
$ (a -> a -> PartialPerm a -> Maybe (PartialPerm a))
-> [a] -> [a] -> [PartialPerm a -> Maybe (PartialPerm a)]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith a -> a -> PartialPerm a -> Maybe (PartialPerm a)
forall a. Ord a => a -> a -> PartialPerm a -> Maybe (PartialPerm a)
extendPP [a]
xs [a]
ys