ADPfusion-0.5.2.0: ADP/Fusion/Core/TyLvlIx.hs
-- | Type-level indexing functionality
module ADP.Fusion.Core.TyLvlIx where
import Data.Proxy
import GHC.TypeLits
import Data.PrimitiveArray hiding (map)
import ADP.Fusion.Core.Classes (RunningIndex (..))
-- | Given some complete index list @ixTy@ and some lower-dimensional
-- version @myTy@, walk down along @ixTy@ until we have @is:.i ~ ms:.m@ and
-- return @m@.
class GetIndexGo ixTy myTy (cmp :: Ordering) where
type ResolvedIx ixTy myTy cmp :: *
getIndexGo :: ixTy -> (Proxy myTy) -> (Proxy cmp) -> ResolvedIx ixTy myTy cmp
instance GetIndexGo (ix:.i) (my:.m) EQ where
type ResolvedIx (ix:.i) (my:.m) EQ = i
getIndexGo (ix:.i) _ _ = i
{-# Inline getIndexGo #-}
instance (GetIndexGo ix (my:.m) (CmpNat (ToNat ix) (ToNat (my:.m)))) => GetIndexGo (ix:.i) (my:.m) GT where
type ResolvedIx (ix:.i) (my:.m) GT = ResolvedIx ix (my:.m) (CmpNat (ToNat ix) (ToNat (my:.m)))
getIndexGo (ix:._) p _ = getIndexGo ix p (Proxy :: Proxy (CmpNat (ToNat ix) (ToNat (my:.m))))
{-# Inline getIndexGo #-}
instance (GetIndexGo ix Z (CmpNat (ToNat ix) (ToNat Z))) => GetIndexGo (ix:.i) Z GT where
type ResolvedIx (ix:.i) Z GT = ResolvedIx ix Z (CmpNat (ToNat ix) (ToNat Z))
getIndexGo (ix:._) p _ = getIndexGo ix p (Proxy :: Proxy (CmpNat (ToNat ix) (ToNat Z)))
{-# Inline getIndexGo #-}
instance GetIndexGo Z Z EQ where
type ResolvedIx Z Z EQ = Z
getIndexGo _ _ _ = Z
{-# Inline getIndexGo #-}
instance GetIndexGo (RunningIndex (ix:.i)) (RunningIndex (my:.m)) EQ where
type ResolvedIx (RunningIndex (ix:.i)) (RunningIndex (my:.m)) EQ = RunningIndex i
getIndexGo (ix:.:i) _ _ = i
{-# Inline getIndexGo #-}
instance
( GetIndexGo (RunningIndex ix) (RunningIndex (my:.m)) (CmpNat (ToNat (RunningIndex ix)) (ToNat (RunningIndex (my:.m))))
) => GetIndexGo (RunningIndex (ix:.i)) (RunningIndex (my:.m)) GT where
type ResolvedIx (RunningIndex (ix:.i)) (RunningIndex (my:.m)) GT = ResolvedIx (RunningIndex ix) (RunningIndex (my:.m)) (CmpNat (ToNat (RunningIndex ix)) (ToNat (RunningIndex (my:.m))))
getIndexGo (ix:.:_) p _ = getIndexGo ix p (Proxy :: Proxy (CmpNat (ToNat (RunningIndex ix)) (ToNat (RunningIndex (my:.m)))))
{-# Inline getIndexGo #-}
instance
( GetIndexGo (RunningIndex ix) (RunningIndex Z) (CmpNat (ToNat (RunningIndex ix)) (ToNat (RunningIndex Z)))
) => GetIndexGo (RunningIndex (ix:.i)) (RunningIndex Z) GT where
type ResolvedIx (RunningIndex (ix:.i)) (RunningIndex Z) GT = ResolvedIx (RunningIndex ix) (RunningIndex Z) (CmpNat (ToNat (RunningIndex ix)) (ToNat (RunningIndex Z)))
getIndexGo (ix:.:_) p _ = getIndexGo ix p (Proxy :: Proxy (CmpNat (ToNat (RunningIndex ix)) (ToNat (RunningIndex Z))))
{-# Inline getIndexGo #-}
instance GetIndexGo (RunningIndex Z) (RunningIndex Z) EQ where
type ResolvedIx (RunningIndex Z) (RunningIndex Z) EQ = RunningIndex Z
getIndexGo _ _ _ = RiZ
{-# Inline getIndexGo #-}
-- | Wrap @GetIndexGo@ and the type-level shenanigans.
type GetIndex l r = GetIndexGo l r (CmpNat (ToNat l) (ToNat r))
type GetIx l r = ResolvedIx l r (CmpNat (ToNat l) (ToNat r))
-- | Simplifying wrapper around @getIndexGo@.
getIndex
:: forall ixTy myTy
. GetIndex ixTy myTy
=> ixTy
-> Proxy myTy
-> GetIx ixTy myTy
getIndex ixTy myTy = getIndexGo ixTy (Proxy :: Proxy myTy) (Proxy :: Proxy (CmpNat (ToNat ixTy) (ToNat myTy)))
{-# Inline getIndex #-}
-- | Given some index structure @x@, return the dimensional number in
-- @Nat@s.
type family ToNat x :: Nat
type instance ToNat Z = 0
type instance ToNat (is:.i) = ToNat is + 1
type instance ToNat (RunningIndex Z) = 0
type instance ToNat (RunningIndex (is:.i)) = ToNat (RunningIndex is) + 1
{-
testggg :: (Z:.Int:.Char) -> Int
testggg ab = getIndex ab (Proxy :: Proxy (Z:.Int)) -- (Z:.(3::Int))
{-# NoInline testggg #-}
-}