1 {-# LANGUAGE TypeFamilies, TypeOperators, ScopedTypeVariables, FlexibleInstances, TemplateHaskell, Rank2Types, FlexibleContexts #-}
2 module Data.Param.Index
9 import Language.Haskell.TH
10 import Language.Haskell.TH.Syntax (Lift(..))
13 import Types.Data.Num.Decimal.Literals.TH
15 import Data.Param.Integer
17 instance NaturalT nT => Lift (Index nT) where
18 lift (Index i) = sigE [| (Index i) |] (decIndexT (fromIntegerT (undefined :: nT)))
20 decIndexT :: Integer -> Q Type
21 decIndexT n = appT (conT (''Index)) (decLiteralT n)
23 fromNaturalT :: ( NaturalT n
25 , (n :<=: upper) ~ True ) => n -> Index upper
26 fromNaturalT x = Index (fromIntegerT x)
30 , Integral (Unsigned nT)
31 ) => Unsigned nT -> Index ((Pow2 nT) :-: D1)
32 fromUnsigned unsigned = Index (toInteger unsigned)
34 rangeT :: Index nT -> nT
37 instance NaturalT nT => Eq (Index nT) where
38 (Index x) == (Index y) = x == y
39 (Index x) /= (Index y) = x /= y
41 instance NaturalT nT => Show (Index nT) where
43 showsPrec prec $ toInteger n
45 instance NaturalT nT => Ord (Index nT) where
46 a `compare` b = toInteger a `compare` toInteger b
48 instance NaturalT nT => Bounded (Index nT) where
50 maxBound = Index (fromIntegerT (undefined :: nT))
52 instance NaturalT nT => Enum (Index nT) where
54 | x == maxBound = error $ "Enum.succ{Index " ++ show (fromIntegerT (undefined :: nT)) ++ "}: tried to take `succ' of maxBound"
57 | x == minBound = error $ "Enum.succ{Index " ++ show (fromIntegerT (undefined :: nT)) ++ "}: tried to take `pred' of minBound"
61 | x > toInteger (maxBound :: Int) =
62 error $ "Enum.fromEnum{Index " ++ show (fromIntegerT (undefined :: nT)) ++ "}: tried to take `fromEnum' on Index greater than maxBound :: Int"
63 | x < toInteger (minBound :: Int) =
64 error $ "Enum.fromEnum{Index " ++ show (fromIntegerT (undefined :: nT)) ++ "}: tried to take `fromEnum' on Index smaller than minBound :: Int"
68 | x > fromIntegral (maxBound :: Index nT) =
69 error $ "Enum.fromEnum{Index " ++ show (fromIntegerT (undefined :: nT)) ++ "}: tried to take `fromEnum' on Index greater than maxBound :: Index " ++ show (fromIntegerT (undefined :: nT))
70 | x < fromIntegral (minBound :: Index nT) =
71 error $ "Enum.fromEnum{Index " ++ show (fromIntegerT (undefined :: nT)) ++ "}: tried to take `fromEnum' on Index smaller than minBound :: Index " ++ show (fromIntegerT (undefined :: nT))
73 fromInteger $ toInteger x
75 instance NaturalT nT => Num (Index nT) where
76 (Index a) + (Index b) =
78 (Index a) * (Index b) =
80 (Index a) - (Index b) =
83 | n > fromIntegerT (undefined :: nT) =
84 error $ "Num.fromInteger{Index " ++ show (fromIntegerT (undefined :: nT)) ++ "}: tried to make Index larger than " ++ show (fromIntegerT (undefined :: nT)) ++ ", n: " ++ show n
87 error $ "Num.fromInteger{Index " ++ show (fromIntegerT (undefined :: nT)) ++ "}: tried to make Index smaller than 0, n: " ++ show n
97 instance NaturalT nT => Real (Index nT) where
98 toRational n = toRational $ toInteger n
100 instance NaturalT nT => Integral (Index nT) where
102 let (quot, rem) = toInteger a `quotRem` toInteger b
103 in (fromInteger quot, fromInteger rem)
104 toInteger s@(Index x) = x