module Sym.Permgram
(
Label
, Permgram
, perm
, label
, size
, permgram
, inverse
) where
import Data.Ord
import Data.List
import Control.Monad
import Control.Applicative
import Sym.Perm (Perm, unsafeAt)
import qualified Sym.Perm as P
import Data.Vector (Vector, (!))
import qualified Data.Vector as V
type Label a = Vector a
data Permgram a = PGram {
perm :: Perm
, label :: Label a
}
constituents :: Permgram a -> (Perm, [a])
constituents (PGram v f) = (v, V.toList f)
instance Show a => Show (Permgram a) where
show w =
let (v, ys) = constituents w
in unwords ["permgram", "(" ++ show v ++ ")", show ys]
instance Eq a => Eq (Permgram a) where
u == v = constituents u == constituents v
instance Ord a => Ord (Permgram a) where
compare u v =
case comparing size u v of
EQ -> comparing constituents u v
x -> x
permgram :: Perm -> [a] -> Permgram a
permgram v = PGram v . V.fromListN (P.size v) . cycle
inverse :: Permgram a -> Permgram a
inverse (PGram u f) = PGram (P.fromList v) (V.fromListN n (map (f!) v))
where
v = map snd . sort $ zip (P.toList u) [0..]
n = P.size u
size :: Permgram a -> Int
size = P.size . perm
instance Functor Permgram where
fmap f w = w { label = V.map f (label w) }
instance Monad Permgram where
return x = permgram (P.fromList [0]) [x]
w >>= f = joinPermgram $ fmap f w
instance Applicative Permgram where
pure = return
(<*>) = ap
joinPermgram :: Permgram (Permgram a) -> Permgram a
joinPermgram w@(PGram u f) = PGram (P.fromList xs) (V.fromListN m ys)
where
len = V.map size f
m = sum $ V.toList len
n = size w
uInverse = map snd . sort $ zip (P.toList u) [0..]
a = V.fromListN n . scanl (+) 0 $ map (len!) uInverse
(xs, ys) = unzip $ do
i <- [0..n1]
let PGram v g = f ! i
let d = a ! (u `unsafeAt` i)
[ (d + v `P.unsafeAt` j, g!j) | j <- [0 .. len!i 1] ]