diff options
| author | Tom Smeding <tom@tomsmeding.com> | 2024-05-28 09:35:06 +0200 | 
|---|---|---|
| committer | Tom Smeding <tom@tomsmeding.com> | 2024-05-28 09:35:21 +0200 | 
| commit | 95544b35615f6714fbef914cb6f2935a088e4d06 (patch) | |
| tree | 21b7902cd296f78bb42bc05e57112090b84bf65e /src/Data | |
| parent | 0221ab67e7bfa6297e3b38f25e23da62c824b742 (diff) | |
Add invertPermutation
Diffstat (limited to 'src/Data')
| -rw-r--r-- | src/Data/Array/Mixed.hs | 39 | 
1 files changed, 39 insertions, 0 deletions
| diff --git a/src/Data/Array/Mixed.hs b/src/Data/Array/Mixed.hs index f7fca0f..065756d 100644 --- a/src/Data/Array/Mixed.hs +++ b/src/Data/Array/Mixed.hs @@ -34,6 +34,7 @@ import Data.Coerce  import qualified Data.Foldable as Foldable  import Data.Functor.Const  import Data.Kind +import Data.List (sort)  import Data.Monoid (Sum(..))  import Data.Proxy  import Data.Type.Bool @@ -259,6 +260,17 @@ instance Show (StaticShX sh) where  lengthStaticShX :: StaticShX sh -> Int  lengthStaticShX (StaticShX l) = lengthListX l +geqStaticShX :: StaticShX sh -> StaticShX sh' -> Maybe (sh :~: sh') +geqStaticShX ZKX ZKX = Just Refl +geqStaticShX (SKnown n@SNat :!% sh) (SKnown m@SNat :!% sh') +  | Just Refl <- sameNat n m +  , Just Refl <- geqStaticShX sh sh' +  = Just Refl +geqStaticShX (SUnknown () :!% sh) (SUnknown () :!% sh') +  | Just Refl <- geqStaticShX sh sh' +  = Just Refl +geqStaticShX _ _ = Nothing +  -- | Evidence for the static part of a shape. This pops up only when you are  -- polymorphic in the element type of an array. @@ -767,6 +779,33 @@ ssxPermutePrefix = coerce (listxPermutePrefix @(SMayNat () SNat))  shPermutePrefix :: HList SNat is -> IShX sh -> IShX (PermutePrefix is sh)  shPermutePrefix = coerce (listxPermutePrefix @(SMayNat Int SNat)) +-- TODO: test this thing more properly +invertPermutation :: HList SNat is +                  -> (forall is'. +                           HList SNat is' +                        -> (forall sh. Rank sh ~ Rank is => StaticShX sh -> Permute is' (Permute is sh) :~: sh) +                        -> r) +                  -> r +invertPermutation = \perm k -> +  genPerm perm $ \invperm -> +    k invperm +      (\ssh -> case provePermInverse perm invperm ssh of +                 Just eq -> eq +                 Nothing -> error $ "invertPermutation: did not generate inverse? perm = " ++ show perm +                                    ++ " ; invperm = " ++ show invperm) +  where +    genPerm :: HList SNat is -> (forall is'. HList SNat is' -> r) -> r +    genPerm perm = +      let permList = foldHList (pure . fromSNat) perm +      in toHList $ map snd (sort (zip permList [0..])) +      where +        toHList :: [Natural] -> (forall is'. HList SNat is' -> r) -> r +        toHList [] k = k HNil +        toHList (n : ns) k = toHList ns $ \l -> TypeNats.withSomeSNat n $ \sn -> k (HCons sn l) + +    provePermInverse :: HList SNat is -> HList SNat is' -> StaticShX sh -> Maybe (Permute is' (Permute is sh) :~: sh) +    provePermInverse perm perminv ssh = geqStaticShX (ssxPermute perminv (ssxPermute perm ssh)) ssh +  class KnownNatList l where makeNatList :: HList SNat l  instance KnownNatList '[] where makeNatList = HNil  instance (KnownNat n, KnownNatList l) => KnownNatList (n : l) where makeNatList = natSing `HCons` makeNatList | 
