parameterized-utils 1.0.1 → 2.0
raw patch · 34 files changed
+2383/−322 lines, 34 filesdep +constraintsdep ~QuickCheckdep ~basedep ~hashablesetup-changednew-uploaderPVP ok
version bump matches the API change (PVP)
Dependencies added: constraints
Dependency ranges changed: QuickCheck, base, hashable, hashtables, lens, tasty, tasty-ant-xml, tasty-hunit, tasty-quickcheck, vector
API changes (from Hackage documentation)
- Data.Parameterized.NatRepr: instance Data.Hashable.Class.Hashable (Data.Parameterized.NatRepr.NatRepr n)
- Data.Parameterized.NatRepr: instance Data.Parameterized.Classes.HashableF Data.Parameterized.NatRepr.NatRepr
- Data.Parameterized.NatRepr: instance Data.Parameterized.Classes.OrdF Data.Parameterized.NatRepr.NatRepr
- Data.Parameterized.NatRepr: instance Data.Parameterized.Classes.PolyEq (Data.Parameterized.NatRepr.NatRepr m) (Data.Parameterized.NatRepr.NatRepr n)
- Data.Parameterized.NatRepr: instance Data.Parameterized.Classes.ShowF Data.Parameterized.NatRepr.NatRepr
- Data.Parameterized.NatRepr: instance Data.Type.Equality.TestEquality Data.Parameterized.NatRepr.NatRepr
- Data.Parameterized.NatRepr: instance GHC.Classes.Eq (Data.Parameterized.NatRepr.NatRepr m)
- Data.Parameterized.NatRepr: instance GHC.Show.Show (Data.Parameterized.NatRepr.NatRepr n)
- Data.Parameterized.NatRepr: instance GHC.TypeNats.KnownNat n => Data.Parameterized.Classes.KnownRepr Data.Parameterized.NatRepr.NatRepr n
+ Data.Parameterized.BoolRepr: (%&&) :: BoolRepr a -> BoolRepr b -> BoolRepr (a && b)
+ Data.Parameterized.BoolRepr: (%||) :: BoolRepr a -> BoolRepr b -> BoolRepr (a || b)
+ Data.Parameterized.BoolRepr: [FalseRepr] :: BoolRepr 'False
+ Data.Parameterized.BoolRepr: [Refl] :: forall k (a :: k) (b :: k). () => a :~: a
+ Data.Parameterized.BoolRepr: [TrueRepr] :: BoolRepr 'True
+ Data.Parameterized.BoolRepr: class TestEquality (f :: k -> Type)
+ Data.Parameterized.BoolRepr: data BoolRepr (b :: Bool)
+ Data.Parameterized.BoolRepr: data Some (f :: k -> *)
+ Data.Parameterized.BoolRepr: data (:~:) (a :: k) (b :: k) :: forall k. () => k -> k -> Type
+ Data.Parameterized.BoolRepr: ifRepr :: BoolRepr a -> BoolRepr b -> BoolRepr c -> BoolRepr (If a b c)
+ Data.Parameterized.BoolRepr: infix 4 :~:
+ Data.Parameterized.BoolRepr: infixr 2 %||
+ Data.Parameterized.BoolRepr: infixr 3 %&&
+ Data.Parameterized.BoolRepr: instance Data.Hashable.Class.Hashable (Data.Parameterized.BoolRepr.BoolRepr n)
+ Data.Parameterized.BoolRepr: instance Data.Parameterized.Classes.HashableF Data.Parameterized.BoolRepr.BoolRepr
+ Data.Parameterized.BoolRepr: instance Data.Parameterized.Classes.KnownRepr Data.Parameterized.BoolRepr.BoolRepr 'GHC.Types.False
+ Data.Parameterized.BoolRepr: instance Data.Parameterized.Classes.KnownRepr Data.Parameterized.BoolRepr.BoolRepr 'GHC.Types.True
+ Data.Parameterized.BoolRepr: instance Data.Parameterized.Classes.OrdF Data.Parameterized.BoolRepr.BoolRepr
+ Data.Parameterized.BoolRepr: instance Data.Parameterized.Classes.PolyEq (Data.Parameterized.BoolRepr.BoolRepr m) (Data.Parameterized.BoolRepr.BoolRepr n)
+ Data.Parameterized.BoolRepr: instance Data.Parameterized.Classes.ShowF Data.Parameterized.BoolRepr.BoolRepr
+ Data.Parameterized.BoolRepr: instance Data.Parameterized.DecidableEq.DecidableEq Data.Parameterized.BoolRepr.BoolRepr
+ Data.Parameterized.BoolRepr: instance Data.Type.Equality.TestEquality Data.Parameterized.BoolRepr.BoolRepr
+ Data.Parameterized.BoolRepr: instance GHC.Classes.Eq (Data.Parameterized.BoolRepr.BoolRepr m)
+ Data.Parameterized.BoolRepr: instance GHC.Show.Show (Data.Parameterized.BoolRepr.BoolRepr m)
+ Data.Parameterized.BoolRepr: notRepr :: BoolRepr b -> BoolRepr (Not b)
+ Data.Parameterized.BoolRepr: someBool :: Bool -> Some BoolRepr
+ Data.Parameterized.BoolRepr: testEquality :: TestEquality f => f a -> f b -> Maybe (a :~: b)
+ Data.Parameterized.BoolRepr: type KnownBool = KnownRepr BoolRepr
+ Data.Parameterized.Classes: infix 4 :~:
+ Data.Parameterized.Classes: instance forall k1 k2 (f :: k2 -> *) (g :: k1 -> k2). Data.Parameterized.Classes.OrdF f => Data.Parameterized.Classes.OrdF (Data.Functor.Compose.Compose f g)
+ Data.Parameterized.Classes: ordFCompose :: forall (f :: k -> *) (g :: l -> k) x y. (forall w z. f w -> f z -> OrderingF w z) -> Compose f g x -> Compose f g y -> OrderingF x y
+ Data.Parameterized.Classes: type family IxValueF (m :: *) :: k -> *
+ Data.Parameterized.ClassesC: class TestEqualityC t => OrdC (t :: (k -> *) -> *)
+ Data.Parameterized.ClassesC: class TestEqualityC (t :: (k -> *) -> *)
+ Data.Parameterized.ClassesC: compareC :: OrdC t => (forall x y. f x -> g y -> OrderingF x y) -> t f -> t g -> Ordering
+ Data.Parameterized.ClassesC: instance Data.Parameterized.ClassesC.OrdC Data.Parameterized.Some.Some
+ Data.Parameterized.ClassesC: instance Data.Parameterized.ClassesC.TestEqualityC Data.Parameterized.Some.Some
+ Data.Parameterized.ClassesC: testEqualityC :: TestEqualityC t => (forall x y. f x -> f y -> Maybe (x :~: y)) -> t f -> t f -> Bool
+ Data.Parameterized.Compose: instance forall k1 k2 (f :: k2 -> *) (g :: k1 -> k2). Data.Type.Equality.TestEquality f => Data.Type.Equality.TestEquality (Data.Functor.Compose.Compose f g)
+ Data.Parameterized.Compose: testEqualityComposeBare :: forall (f :: k -> *) (g :: l -> k) x y. (forall w z. f w -> f z -> Maybe (w :~: z)) -> Compose f g x -> Compose f g y -> Maybe (x :~: y)
+ Data.Parameterized.Context: appendEmbedding :: Size ctx -> Size ctx' -> CtxEmbedding ctx (ctx <+> ctx')
+ Data.Parameterized.Context: instance (GHC.Base.Applicative m, GHC.Base.Monoid w) => GHC.Base.Applicative (Data.Parameterized.Context.Collector m w)
+ Data.Parameterized.Context: instance forall k (m :: k -> *) (w :: k). GHC.Base.Functor (Data.Parameterized.Context.Collector m w)
+ Data.Parameterized.Context: pattern Empty :: () => ctx ~ EmptyCtx => Assignment f ctx
+ Data.Parameterized.Context: take :: forall f ctx ctx'. Size ctx -> Size ctx' -> Assignment f (ctx <+> ctx') -> Assignment f ctx
+ Data.Parameterized.Context: traverseAndCollect :: (Monoid w, Applicative m) => (forall tp. Index ctx tp -> f tp -> m w) -> Assignment f ctx -> m w
+ Data.Parameterized.Context: type family CurryAssignment (ctx :: Ctx k) (f :: k -> *) (x :: *) :: *
+ Data.Parameterized.Context.Safe: [IsAppend] :: Size app -> IsAppend l (l <+> app)
+ Data.Parameterized.Context.Safe: appendDiff :: Size r -> Diff l (l <+> r)
+ Data.Parameterized.Context.Safe: data IsAppend l r
+ Data.Parameterized.Context.Safe: diffIsAppend :: Diff l r -> IsAppend l r
+ Data.Parameterized.Context.Unsafe: [IsAppend] :: Size app -> IsAppend l (l <+> app)
+ Data.Parameterized.Context.Unsafe: appendDiff :: Size r -> Diff l (l <+> r)
+ Data.Parameterized.Context.Unsafe: data IsAppend l r
+ Data.Parameterized.Context.Unsafe: diffIsAppend :: Diff l r -> IsAppend l r
+ Data.Parameterized.Ctx: type family CheckIx (ctx :: Ctx k) (n :: Nat) (b :: Bool) :: Constraint
+ Data.Parameterized.DecidableEq: class DecidableEq f
+ Data.Parameterized.DecidableEq: decEq :: DecidableEq f => f a -> f b -> Either (a :~: b) ((a :~: b) -> Void)
+ Data.Parameterized.List: infixr 5 :<
+ Data.Parameterized.Map: filter :: (forall tp. f tp -> Bool) -> MapF k f -> MapF k f
+ Data.Parameterized.Map: filterWithKey :: (forall tp. k tp -> f tp -> Bool) -> MapF k f -> MapF k f
+ Data.Parameterized.Map: foldMapWithKey :: Monoid m => (forall s. k s -> a s -> m) -> MapF k a -> m
+ Data.Parameterized.Map: foldlWithKey :: (forall s. b -> k s -> a s -> b) -> b -> MapF k a -> b
+ Data.Parameterized.Map: foldlWithKey' :: (forall s. b -> k s -> a s -> b) -> b -> MapF k a -> b
+ Data.Parameterized.Map: foldrWithKey' :: (forall s. k s -> a s -> b -> b) -> b -> MapF k a -> b
+ Data.Parameterized.Map: mapMaybeWithKey :: (forall tp. k tp -> f tp -> Maybe (g tp)) -> MapF k f -> MapF k g
+ Data.Parameterized.Map: mapWithKey :: (forall tp. ktp tp -> f tp -> g tp) -> MapF ktp f -> MapF ktp g
+ Data.Parameterized.NatRepr: decideLeq :: NatRepr a -> NatRepr b -> Either (LeqProof a b) (LeqProof a b -> Void)
+ Data.Parameterized.NatRepr: infix 4 :~:
+ Data.Parameterized.NatRepr: infixl 6 -
+ Data.Parameterized.NatRepr: infixl 7 *
+ Data.Parameterized.NatRepr: intValue :: NatRepr n -> Integer
+ Data.Parameterized.NatRepr: isZeroOrGT1 :: NatRepr n -> Either (n :~: 0) (LeqProof 1 n)
+ Data.Parameterized.NatRepr: lemmaMul :: 1 <= n => p w -> q n -> (w + ((n - 1) * w)) :~: (n * w)
+ Data.Parameterized.NatRepr: lessThanAsymmetric :: forall m f n. LeqProof (n + 1) m -> LeqProof (m + 1) n -> f n -> Void
+ Data.Parameterized.NatRepr: lessThanIrreflexive :: forall f (a :: Nat). f a -> LeqProof (1 + a) a -> Void
+ Data.Parameterized.NatRepr: mkNatRepr :: Natural -> Some NatRepr
+ Data.Parameterized.NatRepr: natFromZero :: forall h a. NatRepr h -> (forall n. n <= h => NatRepr n -> a) -> [a]
+ Data.Parameterized.NatRepr: natRecBounded :: forall m h f. m <= h => NatRepr m -> NatRepr h -> f 0 -> (forall n. n <= h => NatRepr n -> f n -> f (n + 1)) -> f (m + 1)
+ Data.Parameterized.NatRepr: natRecStrong :: forall p f. NatRepr p -> f 0 -> (forall n. NatRepr n -> (forall m. m <= n => NatRepr m -> f m) -> f (n + 1)) -> f p
+ Data.Parameterized.NatRepr: type family (*) (a :: Nat) (b :: Nat) :: Nat
+ Data.Parameterized.Nonce: countNoncesGenerated :: NonceGenerator m s -> m Integer
+ Data.Parameterized.Peano: [Refl] :: forall k (a :: k) (b :: k). () => a :~: a
+ Data.Parameterized.Peano: [SRepr] :: PeanoRepr n -> PeanoView (S n)
+ Data.Parameterized.Peano: [ZRepr] :: PeanoView Z
+ Data.Parameterized.Peano: class TestEquality (f :: k -> Type)
+ Data.Parameterized.Peano: ctxSizeP :: Assignment f ctx -> PeanoRepr (CtxSizeP ctx)
+ Data.Parameterized.Peano: data Peano
+ Data.Parameterized.Peano: data PeanoRepr (n :: Peano)
+ Data.Parameterized.Peano: data PeanoView (n :: Peano)
+ Data.Parameterized.Peano: data Some (f :: k -> *)
+ Data.Parameterized.Peano: data (:~:) (a :: k) (b :: k) :: forall k. () => k -> k -> Type
+ Data.Parameterized.Peano: geP :: PeanoRepr a -> PeanoRepr b -> BoolRepr (Ge a b)
+ Data.Parameterized.Peano: gtP :: PeanoRepr a -> PeanoRepr b -> BoolRepr (Gt a b)
+ Data.Parameterized.Peano: infix 4 :~:
+ Data.Parameterized.Peano: instance Data.Hashable.Class.Hashable (Data.Parameterized.Peano.PeanoRepr n)
+ Data.Parameterized.Peano: instance Data.Parameterized.Classes.HashableF Data.Parameterized.Peano.PeanoRepr
+ Data.Parameterized.Peano: instance Data.Parameterized.Classes.KnownRepr Data.Parameterized.Peano.PeanoRepr Data.Parameterized.Peano.Z
+ Data.Parameterized.Peano: instance Data.Parameterized.Classes.KnownRepr Data.Parameterized.Peano.PeanoRepr n => Data.Parameterized.Classes.KnownRepr Data.Parameterized.Peano.PeanoRepr (Data.Parameterized.Peano.S n)
+ Data.Parameterized.Peano: instance Data.Parameterized.Classes.OrdF Data.Parameterized.Peano.PeanoRepr
+ Data.Parameterized.Peano: instance Data.Parameterized.Classes.PolyEq (Data.Parameterized.Peano.PeanoRepr m) (Data.Parameterized.Peano.PeanoRepr n)
+ Data.Parameterized.Peano: instance Data.Parameterized.Classes.ShowF Data.Parameterized.Peano.PeanoRepr
+ Data.Parameterized.Peano: instance Data.Parameterized.DecidableEq.DecidableEq Data.Parameterized.Peano.PeanoRepr
+ Data.Parameterized.Peano: instance Data.Type.Equality.TestEquality Data.Parameterized.Peano.PeanoRepr
+ Data.Parameterized.Peano: instance GHC.Classes.Eq (Data.Parameterized.Peano.PeanoRepr m)
+ Data.Parameterized.Peano: instance GHC.Show.Show (Data.Parameterized.Peano.PeanoRepr p)
+ Data.Parameterized.Peano: leP :: PeanoRepr a -> PeanoRepr b -> BoolRepr (Le a b)
+ Data.Parameterized.Peano: ltMinusPlusAxiom :: forall n t t'. Lt t (Minus n t') ~ 'True => PeanoRepr n -> PeanoRepr t -> PeanoRepr t' -> Lt (Plus t' t) n :~: 'True
+ Data.Parameterized.Peano: ltP :: PeanoRepr a -> PeanoRepr b -> BoolRepr (Lt a b)
+ Data.Parameterized.Peano: maxP :: PeanoRepr a -> PeanoRepr b -> PeanoRepr (Max a b)
+ Data.Parameterized.Peano: maxPeano :: PeanoRepr m -> PeanoRepr n -> Some PeanoRepr
+ Data.Parameterized.Peano: minP :: PeanoRepr a -> PeanoRepr b -> PeanoRepr (Min a b)
+ Data.Parameterized.Peano: minPeano :: PeanoRepr m -> PeanoRepr n -> Some PeanoRepr
+ Data.Parameterized.Peano: minusP :: PeanoRepr a -> PeanoRepr b -> PeanoRepr (Minus a b)
+ Data.Parameterized.Peano: minusPlusAxiom :: forall n t t'. PeanoRepr n -> PeanoRepr t -> PeanoRepr t' -> Minus n (Plus t' t) :~: Minus (Minus n t') t
+ Data.Parameterized.Peano: mkPeanoRepr :: Word64 -> Some PeanoRepr
+ Data.Parameterized.Peano: mulP :: PeanoRepr a -> PeanoRepr b -> PeanoRepr (Mul a b)
+ Data.Parameterized.Peano: peanoLength :: [a] -> Some PeanoRepr
+ Data.Parameterized.Peano: peanoValue :: PeanoRepr n -> Word64
+ Data.Parameterized.Peano: peanoView :: PeanoRepr n -> PeanoView n
+ Data.Parameterized.Peano: plusCtxSizeAxiom :: forall t1 t2 f. Assignment f t1 -> Assignment f t2 -> CtxSizeP (t1 <+> t2) :~: Plus (CtxSizeP t2) (CtxSizeP t1)
+ Data.Parameterized.Peano: plusP :: PeanoRepr a -> PeanoRepr b -> PeanoRepr (Plus a b)
+ Data.Parameterized.Peano: predP :: PeanoRepr (S n) -> PeanoRepr n
+ Data.Parameterized.Peano: repeatP :: PeanoRepr m -> (forall a. repr a -> repr (f a)) -> repr s -> repr (Repeat m f s)
+ Data.Parameterized.Peano: somePeano :: Integral a => a -> Maybe (Some PeanoRepr)
+ Data.Parameterized.Peano: succP :: PeanoRepr n -> PeanoRepr (S n)
+ Data.Parameterized.Peano: testEquality :: TestEquality f => f a -> f b -> Maybe (a :~: b)
+ Data.Parameterized.Peano: type KnownPeano = KnownRepr PeanoRepr
+ Data.Parameterized.Peano: type S = 'S
+ Data.Parameterized.Peano: type Z = 'Z
+ Data.Parameterized.Peano: type family Ge (a :: Peano) (b :: Peano) :: Bool
+ Data.Parameterized.Peano: viewRepr :: PeanoView n -> PeanoRepr n
+ Data.Parameterized.Peano: zeroP :: PeanoRepr Z
+ Data.Parameterized.TraversableF: instance forall k l (s :: (k -> *) -> *) (t :: (l -> *) -> k -> *). (Data.Parameterized.TraversableF.FunctorF s, Data.Parameterized.TraversableFC.FunctorFC t) => Data.Parameterized.TraversableF.FunctorF (Data.Functor.Compose.Compose s t)
+ Data.Parameterized.TraversableF: instance forall k l (s :: (k -> *) -> *) (t :: (l -> *) -> k -> *). (Data.Parameterized.TraversableF.TraversableF s, Data.Parameterized.TraversableFC.TraversableFC t) => Data.Parameterized.TraversableF.FoldableF (Data.Functor.Compose.Compose s t)
+ Data.Parameterized.TraversableF: instance forall k l (s :: (k -> *) -> *) (t :: (l -> *) -> k -> *). (Data.Parameterized.TraversableF.TraversableF s, Data.Parameterized.TraversableFC.TraversableFC t) => Data.Parameterized.TraversableF.TraversableF (Data.Functor.Compose.Compose s t)
+ Data.Parameterized.Utils.Endian: BigEndian :: Endian
+ Data.Parameterized.Utils.Endian: LittleEndian :: Endian
+ Data.Parameterized.Utils.Endian: data Endian
+ Data.Parameterized.Utils.Endian: instance GHC.Classes.Eq Data.Parameterized.Utils.Endian.Endian
+ Data.Parameterized.Utils.Endian: instance GHC.Classes.Ord Data.Parameterized.Utils.Endian.Endian
+ Data.Parameterized.Utils.Endian: instance GHC.Show.Show Data.Parameterized.Utils.Endian.Endian
+ Data.Parameterized.Vector: append :: Vector m a -> Vector n a -> Vector (m + n) a
+ Data.Parameterized.Vector: cons :: forall n a. a -> Vector n a -> Vector (n + 1) a
+ Data.Parameterized.Vector: data Vector n a
+ Data.Parameterized.Vector: elemAt :: (i + 1) <= n => NatRepr i -> Vector n a -> a
+ Data.Parameterized.Vector: elemAtMaybe :: Int -> Vector n a -> Maybe a
+ Data.Parameterized.Vector: elemAtUnsafe :: Int -> Vector n a -> a
+ Data.Parameterized.Vector: fromList :: 1 <= n => NatRepr n -> [a] -> Maybe (Vector n a)
+ Data.Parameterized.Vector: generate :: forall h a. NatRepr h -> (forall n. n <= h => NatRepr n -> a) -> Vector (h + 1) a
+ Data.Parameterized.Vector: generateM :: forall m h a. Monad m => NatRepr h -> (forall n. n <= h => NatRepr n -> m a) -> m (Vector (h + 1) a)
+ Data.Parameterized.Vector: insertAt :: (i + 1) <= n => NatRepr i -> a -> Vector n a -> Vector n a
+ Data.Parameterized.Vector: insertAtMaybe :: Int -> a -> Vector n a -> Maybe (Vector n a)
+ Data.Parameterized.Vector: instance Data.Foldable.Foldable (Data.Parameterized.Vector.Vector n)
+ Data.Parameterized.Vector: instance Data.Traversable.Traversable (Data.Parameterized.Vector.Vector n)
+ Data.Parameterized.Vector: instance GHC.Base.Functor (Data.Parameterized.Vector.Vector n)
+ Data.Parameterized.Vector: instance GHC.Classes.Eq a => GHC.Classes.Eq (Data.Parameterized.Vector.Vector n a)
+ Data.Parameterized.Vector: instance GHC.Show.Show a => GHC.Show.Show (Data.Parameterized.Vector.Vector n a)
+ Data.Parameterized.Vector: interleave :: forall n a. 1 <= n => Vector n a -> Vector n a -> Vector (2 * n) a
+ Data.Parameterized.Vector: join :: 1 <= w => NatRepr w -> Vector n (Vector w a) -> Vector (n * w) a
+ Data.Parameterized.Vector: joinWith :: forall f n w. 1 <= w => (forall l. 1 <= l => NatRepr l -> f w -> f l -> f (w + l)) -> NatRepr w -> Vector n (f w) -> f (n * w)
+ Data.Parameterized.Vector: joinWithM :: forall m f n w. (1 <= w, Monad m) => (forall l. 1 <= l => NatRepr l -> f w -> f l -> m (f (w + l))) -> NatRepr w -> Vector n (f w) -> m (f (n * w))
+ Data.Parameterized.Vector: length :: Vector n a -> NatRepr n
+ Data.Parameterized.Vector: lengthInt :: Vector n a -> Int
+ Data.Parameterized.Vector: nonEmpty :: Vector n a -> LeqProof 1 n
+ Data.Parameterized.Vector: reverse :: forall a n. 1 <= n => Vector n a -> Vector n a
+ Data.Parameterized.Vector: rotateL :: Int -> Vector n a -> Vector n a
+ Data.Parameterized.Vector: rotateR :: Int -> Vector n a -> Vector n a
+ Data.Parameterized.Vector: shiftL :: Int -> a -> Vector n a -> Vector n a
+ Data.Parameterized.Vector: shiftR :: Int -> a -> Vector n a -> Vector n a
+ Data.Parameterized.Vector: shuffle :: (Int -> Int) -> Vector n a -> Vector n a
+ Data.Parameterized.Vector: singleton :: forall a. a -> Vector 1 a
+ Data.Parameterized.Vector: slice :: ((i + w) <= n, 1 <= w) => NatRepr i -> NatRepr w -> Vector n a -> Vector w a
+ Data.Parameterized.Vector: snoc :: forall n a. Vector n a -> a -> Vector (n + 1) a
+ Data.Parameterized.Vector: split :: (1 <= w, 1 <= n) => NatRepr n -> NatRepr w -> Vector (n * w) a -> Vector n (Vector w a)
+ Data.Parameterized.Vector: splitWith :: forall f w n. (1 <= w, 1 <= n) => Endian -> (forall i. (i + w) <= (n * w) => NatRepr (n * w) -> NatRepr i -> f (n * w) -> f w) -> NatRepr n -> NatRepr w -> f (n * w) -> Vector n (f w)
+ Data.Parameterized.Vector: splitWithA :: forall f g w n. (Applicative f, 1 <= w, 1 <= n) => Endian -> (forall i. (i + w) <= (n * w) => NatRepr (n * w) -> NatRepr i -> g (n * w) -> f (g w)) -> NatRepr n -> NatRepr w -> g (n * w) -> f (Vector n (g w))
+ Data.Parameterized.Vector: take :: forall n x a. 1 <= n => NatRepr n -> Vector (n + x) a -> Vector n a
+ Data.Parameterized.Vector: toList :: Vector n a -> [a]
+ Data.Parameterized.Vector: uncons :: forall n a. Vector n a -> (a, Either (n :~: 1) (Vector (n - 1) a))
+ Data.Parameterized.Vector: zipWith :: (a -> b -> c) -> Vector n a -> Vector n b -> Vector n c
+ Data.Parameterized.Vector: zipWithM :: Monad m => (a -> b -> m c) -> Vector n a -> Vector n b -> m (Vector n c)
+ Data.Parameterized.Vector: zipWithM_ :: Monad m => (a -> b -> m ()) -> Vector n a -> Vector n b -> m ()
+ Data.Parameterized.WithRepr: class IsRepr (f :: k -> *)
+ Data.Parameterized.WithRepr: instance Data.Parameterized.WithRepr.IsRepr Data.Parameterized.BoolRepr.BoolRepr
+ Data.Parameterized.WithRepr: instance Data.Parameterized.WithRepr.IsRepr Data.Parameterized.NatRepr.Internal.NatRepr
+ Data.Parameterized.WithRepr: instance Data.Parameterized.WithRepr.IsRepr Data.Parameterized.Peano.PeanoRepr
+ Data.Parameterized.WithRepr: instance Data.Parameterized.WithRepr.IsRepr Data.Parameterized.SymbolRepr.SymbolRepr
+ Data.Parameterized.WithRepr: instance forall k (f :: k -> *). Data.Parameterized.WithRepr.IsRepr f => Data.Parameterized.WithRepr.IsRepr (Data.Parameterized.Context.Unsafe.Assignment f)
+ Data.Parameterized.WithRepr: instance forall k (f :: k -> *). Data.Parameterized.WithRepr.IsRepr f => Data.Parameterized.WithRepr.IsRepr (Data.Parameterized.List.List f)
+ Data.Parameterized.WithRepr: withRepr :: IsRepr f => f a -> (KnownRepr f a => r) -> r
- Data.Parameterized.Classes: [Refl] :: a :~: a
+ Data.Parameterized.Classes: [Refl] :: forall k (a :: k) (b :: k). () => a :~: a
- Data.Parameterized.Classes: class TestEquality (f :: k -> *)
+ Data.Parameterized.Classes: class TestEquality (f :: k -> Type)
- Data.Parameterized.Classes: data (:~:) (a :: k) (b :: k) :: forall k. () => k -> k -> *
+ Data.Parameterized.Classes: data (:~:) (a :: k) (b :: k) :: forall k. () => k -> k -> Type
- Data.Parameterized.Classes: testEquality :: TestEquality f => f a -> f b -> Maybe a :~: b
+ Data.Parameterized.Classes: testEquality :: TestEquality f => f a -> f b -> Maybe (a :~: b)
- Data.Parameterized.Context: i1of2 :: Index (EmptyCtx ::> a ::> b) a
+ Data.Parameterized.Context: i1of2 :: Index ((EmptyCtx ::> a) ::> b) a
- Data.Parameterized.Context: i1of3 :: Index (EmptyCtx ::> a ::> b ::> c) a
+ Data.Parameterized.Context: i1of3 :: Index (((EmptyCtx ::> a) ::> b) ::> c) a
- Data.Parameterized.Context: i1of4 :: Index (EmptyCtx ::> a ::> b ::> c ::> d) a
+ Data.Parameterized.Context: i1of4 :: Index ((((EmptyCtx ::> a) ::> b) ::> c) ::> d) a
- Data.Parameterized.Context: i1of5 :: Index (EmptyCtx ::> a ::> b ::> c ::> d ::> e) a
+ Data.Parameterized.Context: i1of5 :: Index (((((EmptyCtx ::> a) ::> b) ::> c) ::> d) ::> e) a
- Data.Parameterized.Context: i1of6 :: Index (EmptyCtx ::> a ::> b ::> c ::> d ::> e ::> f) a
+ Data.Parameterized.Context: i1of6 :: Index ((((((EmptyCtx ::> a) ::> b) ::> c) ::> d) ::> e) ::> f) a
- Data.Parameterized.Context: i2of2 :: Index (EmptyCtx ::> a ::> b) b
+ Data.Parameterized.Context: i2of2 :: Index ((EmptyCtx ::> a) ::> b) b
- Data.Parameterized.Context: i2of3 :: Index (EmptyCtx ::> a ::> b ::> c) b
+ Data.Parameterized.Context: i2of3 :: Index (((EmptyCtx ::> a) ::> b) ::> c) b
- Data.Parameterized.Context: i2of4 :: Index (EmptyCtx ::> a ::> b ::> c ::> d) b
+ Data.Parameterized.Context: i2of4 :: Index ((((EmptyCtx ::> a) ::> b) ::> c) ::> d) b
- Data.Parameterized.Context: i2of5 :: Index (EmptyCtx ::> a ::> b ::> c ::> d ::> e) b
+ Data.Parameterized.Context: i2of5 :: Index (((((EmptyCtx ::> a) ::> b) ::> c) ::> d) ::> e) b
- Data.Parameterized.Context: i2of6 :: Index (EmptyCtx ::> a ::> b ::> c ::> d ::> e ::> f) b
+ Data.Parameterized.Context: i2of6 :: Index ((((((EmptyCtx ::> a) ::> b) ::> c) ::> d) ::> e) ::> f) b
- Data.Parameterized.Context: i3of3 :: Index (EmptyCtx ::> a ::> b ::> c) c
+ Data.Parameterized.Context: i3of3 :: Index (((EmptyCtx ::> a) ::> b) ::> c) c
- Data.Parameterized.Context: i3of4 :: Index (EmptyCtx ::> a ::> b ::> c ::> d) c
+ Data.Parameterized.Context: i3of4 :: Index ((((EmptyCtx ::> a) ::> b) ::> c) ::> d) c
- Data.Parameterized.Context: i3of5 :: Index (EmptyCtx ::> a ::> b ::> c ::> d ::> e) c
+ Data.Parameterized.Context: i3of5 :: Index (((((EmptyCtx ::> a) ::> b) ::> c) ::> d) ::> e) c
- Data.Parameterized.Context: i3of6 :: Index (EmptyCtx ::> a ::> b ::> c ::> d ::> e ::> f) c
+ Data.Parameterized.Context: i3of6 :: Index ((((((EmptyCtx ::> a) ::> b) ::> c) ::> d) ::> e) ::> f) c
- Data.Parameterized.Context: i4of4 :: Index (EmptyCtx ::> a ::> b ::> c ::> d) d
+ Data.Parameterized.Context: i4of4 :: Index ((((EmptyCtx ::> a) ::> b) ::> c) ::> d) d
- Data.Parameterized.Context: i4of5 :: Index (EmptyCtx ::> a ::> b ::> c ::> d ::> e) d
+ Data.Parameterized.Context: i4of5 :: Index (((((EmptyCtx ::> a) ::> b) ::> c) ::> d) ::> e) d
- Data.Parameterized.Context: i4of6 :: Index (EmptyCtx ::> a ::> b ::> c ::> d ::> e ::> f) d
+ Data.Parameterized.Context: i4of6 :: Index ((((((EmptyCtx ::> a) ::> b) ::> c) ::> d) ::> e) ::> f) d
- Data.Parameterized.Context: i5of5 :: Index (EmptyCtx ::> a ::> b ::> c ::> d ::> e) e
+ Data.Parameterized.Context: i5of5 :: Index (((((EmptyCtx ::> a) ::> b) ::> c) ::> d) ::> e) e
- Data.Parameterized.Context: i5of6 :: Index (EmptyCtx ::> a ::> b ::> c ::> d ::> e ::> f) e
+ Data.Parameterized.Context: i5of6 :: Index ((((((EmptyCtx ::> a) ::> b) ::> c) ::> d) ::> e) ::> f) e
- Data.Parameterized.Context: i6of6 :: Index (EmptyCtx ::> a ::> b ::> c ::> d ::> e ::> f) f
+ Data.Parameterized.Context: i6of6 :: Index ((((((EmptyCtx ::> a) ::> b) ::> c) ::> d) ::> e) ::> f) f
- Data.Parameterized.Context: size2 :: Size (EmptyCtx ::> a ::> b)
+ Data.Parameterized.Context: size2 :: Size ((EmptyCtx ::> a) ::> b)
- Data.Parameterized.Context: size3 :: Size (EmptyCtx ::> a ::> b ::> c)
+ Data.Parameterized.Context: size3 :: Size (((EmptyCtx ::> a) ::> b) ::> c)
- Data.Parameterized.Context: size4 :: Size (EmptyCtx ::> a ::> b ::> c ::> d)
+ Data.Parameterized.Context: size4 :: Size ((((EmptyCtx ::> a) ::> b) ::> c) ::> d)
- Data.Parameterized.Context: size5 :: Size (EmptyCtx ::> a ::> b ::> c ::> d ::> e)
+ Data.Parameterized.Context: size5 :: Size (((((EmptyCtx ::> a) ::> b) ::> c) ::> d) ::> e)
- Data.Parameterized.Context: size6 :: Size (EmptyCtx ::> a ::> b ::> c ::> d ::> e ::> f)
+ Data.Parameterized.Context: size6 :: Size ((((((EmptyCtx ::> a) ::> b) ::> c) ::> d) ::> e) ::> f)
- Data.Parameterized.Context: uncurryAssignment :: CurryAssignmentClass ctx => CurryAssignment ctx f x -> (Assignment f ctx -> x)
+ Data.Parameterized.Context: uncurryAssignment :: CurryAssignmentClass ctx => CurryAssignment ctx f x -> Assignment f ctx -> x
- Data.Parameterized.Context.Safe: [IncSize] :: !(Size ctx) -> SizeView (ctx ::> tp)
+ Data.Parameterized.Context.Safe: [IncSize] :: !Size ctx -> SizeView (ctx ::> tp)
- Data.Parameterized.Context.Unsafe: [IncSize] :: !(Size ctx) -> SizeView (ctx ::> tp)
+ Data.Parameterized.Context.Unsafe: [IncSize] :: !Size ctx -> SizeView (ctx ::> tp)
- Data.Parameterized.Ctx.Proofs: assoc :: p x -> q y -> r z -> x <+> (y <+> z) :~: (x <+> y) <+> z
+ Data.Parameterized.Ctx.Proofs: assoc :: p x -> q y -> r z -> (x <+> (y <+> z)) :~: ((x <+> y) <+> z)
- Data.Parameterized.HashTable: data RealWorld
+ Data.Parameterized.HashTable: data RealWorld :: Type
- Data.Parameterized.List: [IndexThere] :: !(Index r y) -> Index (x : r) y
+ Data.Parameterized.List: [IndexThere] :: !Index r y -> Index (x : r) y
- Data.Parameterized.List: index1 :: Index (x0 : x1 : r) x1
+ Data.Parameterized.List: index1 :: Index (x0 : (x1 : r)) x1
- Data.Parameterized.List: index2 :: Index (x0 : x1 : x2 : r) x2
+ Data.Parameterized.List: index2 :: Index (x0 : (x1 : (x2 : r))) x2
- Data.Parameterized.List: index3 :: Index (x0 : x1 : x2 : x3 : r) x3
+ Data.Parameterized.List: index3 :: Index (x0 : (x1 : (x2 : (x3 : r)))) x3
- Data.Parameterized.Map: [Pair] :: !(a tp) -> !(b tp) -> Pair a b
+ Data.Parameterized.Map: [Pair] :: !a tp -> !b tp -> Pair a b
- Data.Parameterized.NatRepr: [LeqProof] :: (m <= n) => LeqProof m n
+ Data.Parameterized.NatRepr: [LeqProof] :: m <= n => LeqProof m n
- Data.Parameterized.NatRepr: [NatGT] :: x + 1 <= x + (y + 1) => !(NatRepr y) -> NatComparison (x + (y + 1)) x
+ Data.Parameterized.NatRepr: [NatGT] :: (x + 1) <= (x + (y + 1)) => !NatRepr y -> NatComparison (x + (y + 1)) x
- Data.Parameterized.NatRepr: [NatLT] :: x + 1 <= x + (y + 1) => !(NatRepr y) -> NatComparison x (x + (y + 1))
+ Data.Parameterized.NatRepr: [NatLT] :: (x + 1) <= (x + (y + 1)) => !NatRepr y -> NatComparison x (x + (y + 1))
- Data.Parameterized.NatRepr: [Refl] :: a :~: a
+ Data.Parameterized.NatRepr: [Refl] :: forall k (a :: k) (b :: k). () => a :~: a
- Data.Parameterized.NatRepr: class TestEquality (f :: k -> *)
+ Data.Parameterized.NatRepr: class TestEquality (f :: k -> Type)
- Data.Parameterized.NatRepr: data (:~:) (a :: k) (b :: k) :: forall k. () => k -> k -> *
+ Data.Parameterized.NatRepr: data (:~:) (a :: k) (b :: k) :: forall k. () => k -> k -> Type
- Data.Parameterized.NatRepr: decNat :: (1 <= n) => NatRepr n -> NatRepr (n - 1)
+ Data.Parameterized.NatRepr: decNat :: 1 <= n => NatRepr n -> NatRepr (n - 1)
- Data.Parameterized.NatRepr: divNat :: (1 <= n) => NatRepr (m * n) -> NatRepr n -> NatRepr m
+ Data.Parameterized.NatRepr: divNat :: 1 <= n => NatRepr (m * n) -> NatRepr n -> NatRepr m
- Data.Parameterized.NatRepr: leqMulMono :: (1 <= x) => p x -> q y -> LeqProof y (x * y)
+ Data.Parameterized.NatRepr: leqMulMono :: 1 <= x => p x -> q y -> LeqProof y (x * y)
- Data.Parameterized.NatRepr: leqProof :: (m <= n) => f m -> g n -> LeqProof m n
+ Data.Parameterized.NatRepr: leqProof :: m <= n => f m -> g n -> LeqProof m n
- Data.Parameterized.NatRepr: maxSigned :: (1 <= w) => NatRepr w -> Integer
+ Data.Parameterized.NatRepr: maxSigned :: 1 <= w => NatRepr w -> Integer
- Data.Parameterized.NatRepr: minSigned :: (1 <= w) => NatRepr w -> Integer
+ Data.Parameterized.NatRepr: minSigned :: 1 <= w => NatRepr w -> Integer
- Data.Parameterized.NatRepr: minusPlusCancel :: forall f m g n. (n <= m) => f m -> g n -> (m - n) + n :~: m
+ Data.Parameterized.NatRepr: minusPlusCancel :: forall f m g n. n <= m => f m -> g n -> ((m - n) + n) :~: m
- Data.Parameterized.NatRepr: mulCancelR :: (1 <= c, (n1 * c) ~ (n2 * c)) => f1 n1 -> f2 n2 -> f3 c -> (n1 :~: n2)
+ Data.Parameterized.NatRepr: mulCancelR :: (1 <= c, (n1 * c) ~ (n2 * c)) => f1 n1 -> f2 n2 -> f3 c -> n1 :~: n2
- Data.Parameterized.NatRepr: natRec :: forall m f. NatRepr m -> f 0 -> (forall n. NatRepr n -> f n -> f (n + 1)) -> f m
+ Data.Parameterized.NatRepr: natRec :: forall p f. NatRepr p -> f 0 -> (forall n. NatRepr n -> f n -> f (n + 1)) -> f p
- Data.Parameterized.NatRepr: natValue :: NatRepr n -> Integer
+ Data.Parameterized.NatRepr: natValue :: NatRepr n -> Natural
- Data.Parameterized.NatRepr: plusComm :: forall f m g n. f m -> g n -> m + n :~: n + m
+ Data.Parameterized.NatRepr: plusComm :: forall f m g n. f m -> g n -> (m + n) :~: (n + m)
- Data.Parameterized.NatRepr: plusMinusCancel :: forall f m g n. f m -> g n -> (m + n) - n :~: m
+ Data.Parameterized.NatRepr: plusMinusCancel :: forall f m g n. f m -> g n -> ((m + n) - n) :~: m
- Data.Parameterized.NatRepr: signedClamp :: (1 <= w) => NatRepr w -> Integer -> Integer
+ Data.Parameterized.NatRepr: signedClamp :: 1 <= w => NatRepr w -> Integer -> Integer
- Data.Parameterized.NatRepr: someNat :: Integer -> Maybe (Some NatRepr)
+ Data.Parameterized.NatRepr: someNat :: Integral a => a -> Maybe (Some NatRepr)
- Data.Parameterized.NatRepr: subNat :: (n <= m) => NatRepr m -> NatRepr n -> NatRepr (m - n)
+ Data.Parameterized.NatRepr: subNat :: n <= m => NatRepr m -> NatRepr n -> NatRepr (m - n)
- Data.Parameterized.NatRepr: testEquality :: TestEquality f => f a -> f b -> Maybe a :~: b
+ Data.Parameterized.NatRepr: testEquality :: TestEquality f => f a -> f b -> Maybe (a :~: b)
- Data.Parameterized.NatRepr: testStrictLeq :: forall m n. (m <= n) => NatRepr m -> NatRepr n -> Either (LeqProof (m + 1) n) (m :~: n)
+ Data.Parameterized.NatRepr: testStrictLeq :: forall m n. m <= n => NatRepr m -> NatRepr n -> Either (LeqProof (m + 1) n) (m :~: n)
- Data.Parameterized.NatRepr: toSigned :: (1 <= w) => NatRepr w -> Integer -> Integer
+ Data.Parameterized.NatRepr: toSigned :: 1 <= w => NatRepr w -> Integer -> Integer
- Data.Parameterized.NatRepr: withAddLeq :: forall n m a. NatRepr n -> NatRepr m -> ((n <= n + m) => NatRepr (n + m) -> a) -> a
+ Data.Parameterized.NatRepr: withAddLeq :: forall n m a. NatRepr n -> NatRepr m -> (n <= (n + m) => NatRepr (n + m) -> a) -> a
- Data.Parameterized.NatRepr: withAddMulDistribRight :: forall n m p f g h a. f n -> g m -> h p -> ((((n * p) + (m * p)) ~ ((n + m) * p)) => a) -> a
+ Data.Parameterized.NatRepr: withAddMulDistribRight :: forall n m p f g h a. f n -> g m -> h p -> (((n * p) + (m * p)) ~ ((n + m) * p) => a) -> a
- Data.Parameterized.NatRepr: withAddPrefixLeq :: NatRepr n -> NatRepr m -> ((m <= n + m) => a) -> a
+ Data.Parameterized.NatRepr: withAddPrefixLeq :: NatRepr n -> NatRepr m -> (m <= (n + m) => a) -> a
- Data.Parameterized.NatRepr: withDivModNat :: forall n m a. NatRepr n -> NatRepr m -> (forall div mod. (n ~ ((div * m) + mod)) => NatRepr div -> NatRepr mod -> a) -> a
+ Data.Parameterized.NatRepr: withDivModNat :: forall n m a. NatRepr n -> NatRepr m -> (forall div mod. n ~ ((div * m) + mod) => NatRepr div -> NatRepr mod -> a) -> a
- Data.Parameterized.NatRepr: withLeqProof :: LeqProof m n -> ((m <= n) => a) -> a
+ Data.Parameterized.NatRepr: withLeqProof :: LeqProof m n -> (m <= n => a) -> a
- Data.Parameterized.NatRepr: withSubMulDistribRight :: forall n m p f g h a. (m <= n) => f n -> g m -> h p -> ((((n * p) - (m * p)) ~ ((n - m) * p)) => a) -> a
+ Data.Parameterized.NatRepr: withSubMulDistribRight :: forall n m p f g h a. m <= n => f n -> g m -> h p -> (((n * p) - (m * p)) ~ ((n - m) * p) => a) -> a
- Data.Parameterized.Nonce: freshNonce :: NonceGenerator m s -> forall k (tp :: k). m (Nonce s tp)
+ Data.Parameterized.Nonce: freshNonce :: forall m s k (tp :: k). NonceGenerator m s -> m (Nonce s tp)
- Data.Parameterized.Nonce: withSTNonceGenerator :: (forall s. NonceGenerator (ST t) s -> (ST t) r) -> ST t r
+ Data.Parameterized.Nonce: withSTNonceGenerator :: (forall s. NonceGenerator (ST t) s -> ST t r) -> ST t r
- Data.Parameterized.Pair: [Pair] :: !(a tp) -> !(b tp) -> Pair a b
+ Data.Parameterized.Pair: [Pair] :: !a tp -> !b tp -> Pair a b
- Data.Parameterized.Some: Some :: (f x) -> Some
+ Data.Parameterized.Some: Some :: f x -> Some
- Data.Parameterized.TraversableF: traverseF_ :: (FoldableF t, Applicative f) => (forall s. e s -> f ()) -> t e -> f ()
+ Data.Parameterized.TraversableF: traverseF_ :: (FoldableF t, Applicative f) => (forall s. e s -> f a) -> t e -> f ()
- Data.Parameterized.TraversableFC: allFC :: FoldableFC t => (forall x. f x -> Bool) -> (forall x. t f x -> Bool)
+ Data.Parameterized.TraversableFC: allFC :: FoldableFC t => (forall x. f x -> Bool) -> forall x. t f x -> Bool
- Data.Parameterized.TraversableFC: anyFC :: FoldableFC t => (forall x. f x -> Bool) -> (forall x. t f x -> Bool)
+ Data.Parameterized.TraversableFC: anyFC :: FoldableFC t => (forall x. f x -> Bool) -> forall x. t f x -> Bool
- Data.Parameterized.TraversableFC: compareFC :: forall f. OrdFC t => (forall x y. f x -> f y -> OrderingF x y) -> (forall x y. t f x -> t f y -> OrderingF x y)
+ Data.Parameterized.TraversableFC: compareFC :: forall f. OrdFC t => (forall x y. f x -> f y -> OrderingF x y) -> forall x y. t f x -> t f y -> OrderingF x y
- Data.Parameterized.TraversableFC: fmapFC :: forall f g. FunctorFC t => (forall x. f x -> g x) -> (forall x. t f x -> t g x)
+ Data.Parameterized.TraversableFC: fmapFC :: forall f g. FunctorFC t => (forall x. f x -> g x) -> forall x. t f x -> t g x
- Data.Parameterized.TraversableFC: fmapFCDefault :: TraversableFC t => forall f g. (forall x. f x -> g x) -> (forall x. t f x -> t g x)
+ Data.Parameterized.TraversableFC: fmapFCDefault :: TraversableFC t => forall f g. (forall x. f x -> g x) -> forall x. t f x -> t g x
- Data.Parameterized.TraversableFC: foldMapFC :: forall f m. (FoldableFC t, Monoid m) => (forall x. f x -> m) -> (forall x. t f x -> m)
+ Data.Parameterized.TraversableFC: foldMapFC :: forall f m. (FoldableFC t, Monoid m) => (forall x. f x -> m) -> forall x. t f x -> m
- Data.Parameterized.TraversableFC: foldMapFCDefault :: (TraversableFC t, Monoid m) => (forall x. f x -> m) -> (forall x. t f x -> m)
+ Data.Parameterized.TraversableFC: foldMapFCDefault :: (TraversableFC t, Monoid m) => (forall x. f x -> m) -> forall x. t f x -> m
- Data.Parameterized.TraversableFC: foldlFC :: forall f b. FoldableFC t => (forall x. b -> f x -> b) -> (forall x. b -> t f x -> b)
+ Data.Parameterized.TraversableFC: foldlFC :: forall f b. FoldableFC t => (forall x. b -> f x -> b) -> forall x. b -> t f x -> b
- Data.Parameterized.TraversableFC: foldlFC' :: forall f b. FoldableFC t => (forall x. b -> f x -> b) -> (forall x. b -> t f x -> b)
+ Data.Parameterized.TraversableFC: foldlFC' :: forall f b. FoldableFC t => (forall x. b -> f x -> b) -> forall x. b -> t f x -> b
- Data.Parameterized.TraversableFC: foldrFC :: forall f b. FoldableFC t => (forall x. f x -> b -> b) -> (forall x. b -> t f x -> b)
+ Data.Parameterized.TraversableFC: foldrFC :: forall f b. FoldableFC t => (forall x. f x -> b -> b) -> forall x. b -> t f x -> b
- Data.Parameterized.TraversableFC: foldrFC' :: forall f b. FoldableFC t => (forall x. f x -> b -> b) -> (forall x. b -> t f x -> b)
+ Data.Parameterized.TraversableFC: foldrFC' :: forall f b. FoldableFC t => (forall x. f x -> b -> b) -> forall x. b -> t f x -> b
- Data.Parameterized.TraversableFC: forMFC_ :: (FoldableFC t, Applicative m) => t f c -> (forall x. f x -> m ()) -> m ()
+ Data.Parameterized.TraversableFC: forMFC_ :: (FoldableFC t, Applicative m) => t f c -> (forall x. f x -> m a) -> m ()
- Data.Parameterized.TraversableFC: hashWithSaltFC :: forall f. HashableFC t => (forall x. Int -> f x -> Int) -> (forall x. Int -> t f x -> Int)
+ Data.Parameterized.TraversableFC: hashWithSaltFC :: forall f. HashableFC t => (forall x. Int -> f x -> Int) -> forall x. Int -> t f x -> Int
- Data.Parameterized.TraversableFC: showFC :: forall f. ShowFC t => (forall x. f x -> String) -> (forall x. t f x -> String)
+ Data.Parameterized.TraversableFC: showFC :: forall f. ShowFC t => (forall x. f x -> String) -> forall x. t f x -> String
- Data.Parameterized.TraversableFC: showsPrecFC :: forall f. ShowFC t => (forall x. Int -> f x -> ShowS) -> (forall x. Int -> t f x -> ShowS)
+ Data.Parameterized.TraversableFC: showsPrecFC :: forall f. ShowFC t => (forall x. Int -> f x -> ShowS) -> forall x. Int -> t f x -> ShowS
- Data.Parameterized.TraversableFC: testEqualityFC :: forall f. TestEqualityFC t => (forall x y. f x -> f y -> (Maybe (x :~: y))) -> (forall x y. t f x -> t f y -> (Maybe (x :~: y)))
+ Data.Parameterized.TraversableFC: testEqualityFC :: forall f. TestEqualityFC t => (forall x y. f x -> f y -> Maybe (x :~: y)) -> forall x y. t f x -> t f y -> Maybe (x :~: y)
- Data.Parameterized.TraversableFC: toListFC :: forall f a. FoldableFC t => (forall x. f x -> a) -> (forall x. t f x -> [a])
+ Data.Parameterized.TraversableFC: toListFC :: forall f a. FoldableFC t => (forall x. f x -> a) -> forall x. t f x -> [a]
- Data.Parameterized.TraversableFC: traverseFC :: forall f g m. (TraversableFC t, Applicative m) => (forall x. f x -> m (g x)) -> (forall x. t f x -> m (t g x))
+ Data.Parameterized.TraversableFC: traverseFC :: forall f g m. (TraversableFC t, Applicative m) => (forall x. f x -> m (g x)) -> forall x. t f x -> m (t g x)
- Data.Parameterized.TraversableFC: traverseFC_ :: (FoldableFC t, Applicative m) => (forall x. f x -> m ()) -> (forall x. t f x -> m ())
+ Data.Parameterized.TraversableFC: traverseFC_ :: (FoldableFC t, Applicative m) => (forall x. f x -> m a) -> forall x. t f x -> m ()
- Data.Parameterized.Utils.BinTree: balanceL :: (IsBinTree c e) => e -> c -> c -> c
+ Data.Parameterized.Utils.BinTree: balanceL :: IsBinTree c e => e -> c -> c -> c
- Data.Parameterized.Utils.BinTree: balanceR :: (IsBinTree c e) => e -> c -> c -> c
+ Data.Parameterized.Utils.BinTree: balanceR :: IsBinTree c e => e -> c -> c -> c
- Data.Parameterized.Utils.BinTree: insert :: (IsBinTree c e) => (e -> e -> Ordering) -> e -> c -> Updated c
+ Data.Parameterized.Utils.BinTree: insert :: IsBinTree c e => (e -> e -> Ordering) -> e -> c -> Updated c
- Data.Parameterized.Utils.BinTree: union :: (IsBinTree c e) => (e -> e -> Ordering) -> c -> c -> c
+ Data.Parameterized.Utils.BinTree: union :: IsBinTree c e => (e -> e -> Ordering) -> c -> c -> c
Files
- Changelog.md +138/−0
- Setup.hs +0/−2
- parameterized-utils.cabal +51/−34
- src/Data/Parameterized/BoolRepr.hs +121/−0
- src/Data/Parameterized/Classes.hs +26/−4
- src/Data/Parameterized/ClassesC.hs +53/−0
- src/Data/Parameterized/Compose.hs +46/−0
- src/Data/Parameterized/Context.hs +39/−5
- src/Data/Parameterized/Context/Safe.hs +28/−8
- src/Data/Parameterized/Context/Unsafe.hs +35/−17
- src/Data/Parameterized/Ctx.hs +1/−1
- src/Data/Parameterized/Ctx/Proofs.hs +3/−2
- src/Data/Parameterized/DecidableEq.hs +38/−0
- src/Data/Parameterized/HashTable.hs +5/−4
- src/Data/Parameterized/List.hs +5/−4
- src/Data/Parameterized/Map.hs +99/−40
- src/Data/Parameterized/NatRepr.hs +191/−104
- src/Data/Parameterized/NatRepr/Internal.hs +99/−0
- src/Data/Parameterized/Nonce.hs +51/−44
- src/Data/Parameterized/Nonce/Transformers.hs +3/−2
- src/Data/Parameterized/Pair.hs +2/−1
- src/Data/Parameterized/Peano.hs +501/−0
- src/Data/Parameterized/Some.hs +2/−1
- src/Data/Parameterized/SymbolRepr.hs +2/−3
- src/Data/Parameterized/TH/GADT.hs +16/−11
- src/Data/Parameterized/TraversableF.hs +36/−5
- src/Data/Parameterized/TraversableFC.hs +5/−4
- src/Data/Parameterized/Utils/BinTree.hs +10/−10
- src/Data/Parameterized/Utils/Endian.hs +16/−0
- src/Data/Parameterized/Vector.hs +560/−0
- src/Data/Parameterized/WithRepr.hs +115/−0
- test/Test/Context.hs +14/−16
- test/Test/Vector.hs +70/−0
- test/UnitTest.hs +2/−0
+ Changelog.md view
@@ -0,0 +1,138 @@+# Changelog for the `parameterized-utils` package++## 2.0 -- *2019 Apr 03*++ * Drop support for GHC versions prior to GHC 8.2+ * Various Haddock and module updates.+ * Data.Parameterized.Classes+ - Added function: `ordFCompose`+ - Added `OrdF` instance for `Compose`+ * Data.Parameterized.ClassesC+ - Marked as `Safe` haskell via pragma+ - Added `OrdC` instance for `Some`+ * Data.Parameterized.Compose+ - Update `testEqualityComposeBare` to be more kind-polymorphic.+ - Marked as `Safe` haskell via pragma+ * Data.Parameterized.Context+ - Added `diffIsAppend` function to extract the contextual+ difference between two `Context`s (as a `Diff`) as an `IsAppend`+ (new) data value if the left is a sub-context of the right.+ * Data.Parameterized.NatRepr+ - Change runtime representation from `Int` to `Natural`+ - Add function `intValue` to recover an `Int` from a `NatRepr`.+ - Add constructor function `mkNatRepr` to construct a `NatRepr`+ from a `Natural`.+ - Removed awkward backdoor for directly creating `NatRepr` values;+ the single needed internal usage is now handled internally.+ * Data.Parameterized.Peano+ - Newly added module.+ - Defines a type `Peano` and `PeanoRepr` for representing a+ type-level natural at runtime.+ - The runtime representation of `PeanoRepr` is `Word64`+ - Has both safe and unsafe implementations.+ * Data.Parameterized.WithRepr+ - Newly added module.+ - This module declares a class `IsRepr` with a single method+ `withRepr` that can be used to derive a 'KnownRepr' constraint+ from an explicit 'Repr' argument. Clients of this method need+ only create an empty instance. The default implementation+ suffices.++## 1.0.8 -- *2019 Feb 01*++ * Data.Parameterized.Map+ - Fixed `MapF` functions `filter` and `filterWithKey`+ - Added `MapF` function: `mapWithKey`+ * Data.Parameterized.NatRepr+ - Un-deprecate `withKnownNat`+ * Data.Parameterized.Context+ - Updated some haddock documentation (esp. `CtxEmbedding` data structure).+ * Data.Parameterized.Nonce+ - Fixed `newIONonceGenerator` haddock documentation (IO monad, not ST monad).+ - Added `countNoncesGenerated` for profiling Nonce usage.+ * Data.Parameterized.TraversableF+ - Added `FunctorF`, `FoldableF`, and `TraversableF` instances for+ `Compose` from Data.Functor.Compose+ * Data.Parameterized.ClassesC+ - Newly added module.+ - Declares `TestEqualityC` and `OrdC` classes for working with+ types that have kind `(k -> *) -> *` for any `k`.+ * Data.Parameterized.Compose+ - Newly added module.+ - Orphan instance and `testEqualityComposeBare` function for+ working with Data.Functor.Compose.+ * Data.Parameterized.TestEquality+ - Newly added module.+ - Utilities for working with Data.Type.TestEquality.++## 1.0.7 -- *2018 Nov 17*++ * Data.Parameterized.Map+ - Added `MapF` functions:+ - `filter`+ - `filterWithKey`++## 1.0.6 -- *2018 Nov 19*++ * Add support for GHC 8.6.+ * Data.Parameterized.Map+ - Added functions:+ - `foldlWithKey` and `foldlWithKey'` (strict)+ - `foldrWithKey` and `foldrWithKey'` (strict)+ - `mapMaybeWithKey`++## 1.0.5 -- *2018 Sep 04*++ * Data.Parameterized.Context+ - Add function: `take`, `appendEmbedding`, `appendDiff`+ - Diff is type role nominal in both parameters.++## 1.0.4 -- *2018 Aug 29*++ * Data.Parameterized.Context+ - Add `traverseAndCollect`. Allows traversal of an Assignment in+ order from left to right, collecting the results of a visitor+ function monoidically.+ * Data.Parameterized.DecidableEq+ - Newly added module. The `DecidableEq` class represents+ decideable equality on a type family as a superclass of+ `TestEquality`, where the latter cannot provide evidence of+ non-equality.+ * Data.Parameterized.NatRepr+ - Add `DecidableEq` instance for NatRepr.+ - Add functions:+ - `decideLeq`+ - `isZeroOrGT1`+ - `lessThanIrreflexive`+ - `lessThanAsymmetric`+ - `natRecStrong` -- recursor with strong induction+ - `natRecBounded` -- bounded recursor+ - `natFromZero`+ * Data.Parameterized.Vector+ - Add construction functions: `singleton`, `cons`, `snoc`, `generate`, and `generateM`+ - Add functions: `splitWithA` (applicative `splitWith`).++## 1.0.3 -- *2018 Aug 24*++ * Move `lemmaMul` from Vector to NatRepr.+ * Add stricter role annotations:+ - `NatRepr` is nominal.+ - `Vector` is nominal in the first parameter and representational in the second.+ * Data.Parameterized.NatRepr+ - Provide a backdoor for directly creating `NatRepr` values. Use carefully.+ * Data.Parameterized.Vector+ - Add Show and Eq instances+ - Add functions: `joinWithM`, `reverse`++## 1.0.2 -- *2018 Aug 23*++ * Allow function passed to `traverseF_`, `traverseFC_`, and+ `forMFC_` to return a value instead of null (`()`).+ * Data.Parameterized.Vector+ - Newly added module. A fixed-size vector of typed elements.+ * Data.Parameterized.Utils.Endian+ - Newly added module. Used in Vector.++## 1.0.1 -- *2018 Aug 13*++ Baseline for changelog tracking.
− Setup.hs
@@ -1,2 +0,0 @@-import Distribution.Simple-main = defaultMain
parameterized-utils.cabal view
@@ -1,12 +1,14 @@ Name: parameterized-utils-Version: 1.0.1+Version: 2.0 Author: Galois Inc.-Maintainer: jhendrix@galois.com+Maintainer: jhendrix@galois.com, kquick@galois.com+stability: stable Build-type: Simple Cabal-version: >= 1.9.2-license: BSD3-license-file: LICENSE-category: Data Structures, Dependent Types+Copyright: ©2016-2019 Galois, Inc.+License: BSD3+License-file: LICENSE+category: Data Structures, Dependent Types Synopsis: Classes and data structures for working with data-kind indexed types Description: This packages contains collection classes and type representations@@ -14,6 +16,10 @@ intended for things like expression libraries where one wishes to leverage the Haskell type-checker to improve type-safety by encoding the object language type system into data kinds.+extra-source-files: Changelog.md+homepage: https://github.com/GaloisInc/parameterized-utils+bug-reports: https://github.com/GaloisInc/parameterized-utils/issues+tested-with: GHC==8.2.2, GHC==8.4.4, GHC==8.6.4 -- Many (but not all, sadly) uses of unsafe operations are -- controlled by this compile flag. When this flag is set@@ -21,7 +27,7 @@ -- Unsafe.Coerce and Data.Coerce. These alternate implementations -- impose a significant performance hit. flag unsafe-operations- Description: Use unsafe operations to improve performance+ Description: Use unsafe operations (e.g. coercions) to improve performance Default: True source-repository head@@ -29,30 +35,34 @@ location: https://github.com/GaloisInc/parameterized-utils library- build-depends:- base >= 4.7 && < 4.12,- th-abstraction >=0.1 && <0.3,- containers,- deepseq,- ghc-prim,- hashable,- hashtables,- lens,- mtl,- template-haskell,- text,- vector+ build-depends: base >= 4.10 && < 5+ , th-abstraction >=0.1 && <0.3+ , constraints == 0.10.*+ , containers+ , deepseq+ , ghc-prim+ , hashable == 1.2.*+ , hashtables == 1.2.*+ , lens == 4.17.*+ , mtl+ , template-haskell+ , text+ , vector == 0.12.* hs-source-dirs: src exposed-modules: Data.Parameterized+ Data.Parameterized.BoolRepr Data.Parameterized.Classes+ Data.Parameterized.ClassesC+ Data.Parameterized.Compose Data.Parameterized.Context Data.Parameterized.Context.Safe Data.Parameterized.Context.Unsafe Data.Parameterized.Ctx Data.Parameterized.Ctx.Proofs+ Data.Parameterized.DecidableEq Data.Parameterized.HashTable Data.Parameterized.List Data.Parameterized.Map@@ -60,14 +70,21 @@ Data.Parameterized.Nonce Data.Parameterized.Nonce.Transformers Data.Parameterized.Nonce.Unsafe+ Data.Parameterized.Pair+ Data.Parameterized.Peano Data.Parameterized.Some Data.Parameterized.SymbolRepr- Data.Parameterized.Pair Data.Parameterized.TH.GADT Data.Parameterized.TraversableF Data.Parameterized.TraversableFC Data.Parameterized.Utils.BinTree+ Data.Parameterized.Utils.Endian+ Data.Parameterized.Vector+ Data.Parameterized.WithRepr + other-modules:+ Data.Parameterized.NatRepr.Internal+ ghc-options: -Wall if flag(unsafe-operations)@@ -80,21 +97,21 @@ ghc-options: -Wall - main-is:UnitTest.hs+ main-is: UnitTest.hs other-modules: Test.Context Test.NatRepr+ Test.Vector - build-depends:- base,- hashable,- hashtables,- ghc-prim,- lens,- mtl,- parameterized-utils,- tasty,- tasty-ant-xml,- tasty-hunit,- tasty-quickcheck >= 0.8.1,- QuickCheck >= 2.7+ build-depends: base+ , hashable+ , hashtables+ , ghc-prim+ , lens+ , mtl+ , parameterized-utils+ , tasty == 1.2.*+ , tasty-ant-xml == 1.1.*+ , tasty-hunit >= 0.9 && < 0.11+ , tasty-quickcheck >= 0.8.1 && < 0.11+ , QuickCheck >= 2.7 && < 2.14
+ src/Data/Parameterized/BoolRepr.hs view
@@ -0,0 +1,121 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE EmptyCase #-}+{-# LANGUAGE ExplicitNamespaces #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE PatternGuards #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE RoleAnnotations #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE UndecidableInstances #-}++module Data.Parameterized.BoolRepr+ ( module Data.Type.Bool+ , BoolRepr(..)+ , ifRepr, notRepr, (%&&), (%||)+ , KnownBool++ , someBool++ -- * Re-exports+ , TestEquality(..)+ , (:~:)(..)+ , Data.Parameterized.Some.Some+ )+where++import Data.Parameterized.Classes+import Data.Parameterized.DecidableEq+import Data.Parameterized.Some++import Data.Type.Bool+import Data.Hashable++-- | +data BoolRepr (b :: Bool) where+ FalseRepr :: BoolRepr 'False+ TrueRepr :: BoolRepr 'True++ +-- | conditional +ifRepr :: BoolRepr a -> BoolRepr b -> BoolRepr c -> BoolRepr (If a b c)+ifRepr TrueRepr b _ = b+ifRepr FalseRepr _ c = c++-- | negation+notRepr :: BoolRepr b -> BoolRepr (Not b)+notRepr TrueRepr = FalseRepr+notRepr FalseRepr = TrueRepr++-- | Conjunction +(%&&) :: BoolRepr a -> BoolRepr b -> BoolRepr (a && b)+FalseRepr %&& _ = FalseRepr+TrueRepr %&& a = a+infixr 3 %&&++-- | Disjunction +(%||) :: BoolRepr a -> BoolRepr b -> BoolRepr (a || b)+FalseRepr %|| a = a+TrueRepr %|| _ = TrueRepr+infixr 2 %|| ++instance Hashable (BoolRepr n) where+ hashWithSalt i TrueRepr = hashWithSalt i True+ hashWithSalt i FalseRepr = hashWithSalt i False+++instance Eq (BoolRepr m) where+ _ == _ = True++instance TestEquality BoolRepr where+ testEquality TrueRepr TrueRepr = Just Refl+ testEquality FalseRepr FalseRepr = Just Refl+ testEquality _ _ = Nothing++instance DecidableEq BoolRepr where+ decEq TrueRepr TrueRepr = Left Refl+ decEq FalseRepr FalseRepr = Left Refl+ decEq TrueRepr FalseRepr = Right $ \case {}+ decEq FalseRepr TrueRepr = Right $ \case {}++instance OrdF BoolRepr where+ compareF TrueRepr TrueRepr = EQF+ compareF FalseRepr FalseRepr = EQF+ compareF TrueRepr FalseRepr = GTF+ compareF FalseRepr TrueRepr = LTF++instance PolyEq (BoolRepr m) (BoolRepr n) where+ polyEqF x y = (\Refl -> Refl) <$> testEquality x y++instance Show (BoolRepr m) where+ show FalseRepr = "FalseRepr"+ show TrueRepr = "TrueRepr"+ +instance ShowF BoolRepr++instance HashableF BoolRepr where+ hashWithSaltF = hashWithSalt+++----------------------------------------------------------+-- * Implicit runtime booleans++type KnownBool = KnownRepr BoolRepr++instance KnownRepr BoolRepr 'True where+ knownRepr = TrueRepr+instance KnownRepr BoolRepr 'False where+ knownRepr = FalseRepr++someBool :: Bool -> Some BoolRepr+someBool True = Some TrueRepr+someBool False = Some FalseRepr
src/Data/Parameterized/Classes.hs view
@@ -1,6 +1,7 @@ {-|-Copyright : (c) Galois, Inc 2014-2015-Maintainer : Joe Hendrix <jhendrix@galois.com>+Description : Classes for working with type of kind @k -> *@+Copyright : (c) Galois, Inc 2014-2019+Maintainer : Joe Hendrix <jhendrix@galois.com> This module declares classes for working with types with the kind @k -> *@ for any kind @k@. These are generalizations of the@@ -37,6 +38,7 @@ , orderingF_refl , toOrdering , fromOrdering+ , ordFCompose -- * Typeclass generalizations , ShowF(..) , showsF@@ -55,11 +57,14 @@ ) where import Data.Functor.Const+import Data.Functor.Compose (Compose(..)) import Data.Hashable import Data.Maybe (isJust) import Data.Proxy import Data.Type.Equality as Equality +import Data.Parameterized.Compose ()+ -- We define these type alias here to avoid importing Control.Lens -- modules, as this apparently causes problems with the safe Hasekll -- checking.@@ -134,8 +139,8 @@ fromOrdering EQ = EQF fromOrdering GT = GTF --- | `joinOrderingF x y` first compares on x, returning an equivalent--- value if it is not `EQF`. If it is EQF, it returns `y`.+-- | @joinOrderingF x y@ first compares on @x@, returning an+-- equivalent value if it is not `EQF`. If it is `EQF`, it returns @y@. joinOrderingF :: forall (a :: j) (b :: j) (c :: k) (d :: k) . OrderingF a b -> (a ~ b => OrderingF c d)@@ -193,6 +198,23 @@ -> (a ~ b => OrderingF c d) -> OrderingF c d lexCompareF x y = joinOrderingF (compareF x y)++-- | If the \"outer\" functor has an 'OrdF' instance, then one can be generated+-- for the \"inner\" functor. The type-level evidence of equality is deduced+-- via generativity of @g@, e.g. the inference @g x ~ g y@ implies @x ~ y@.+ordFCompose :: forall (f :: k -> *) (g :: l -> k) x y.+ (forall w z. f w -> f z -> OrderingF w z)+ -> Compose f g x+ -> Compose f g y+ -> OrderingF x y+ordFCompose ordF_ (Compose x) (Compose y) =+ case ordF_ x y of+ LTF -> LTF+ GTF -> GTF+ EQF -> EQF++instance OrdF f => OrdF (Compose f g) where+ compareF x y = ordFCompose compareF x y ------------------------------------------------------------------------ -- ShowF
+ src/Data/Parameterized/ClassesC.hs view
@@ -0,0 +1,53 @@+{-|+Description : Classes for working with type of kind @(k -> *) -> *@+Copyright : (c) Galois, Inc 2014-2019+Maintainer : Langston Barrett <langston@galois.com>++This module declares classes for working with types with the kind+@(k -> *) -> *@ for any kind @k@.++These classes generally require type-level evidence for operations+on their subterms, but don't actually provide it themselves (because+their types are not themselves parameterized, unlike those in+"Data.Parameterized.TraverableFC").++Note that there is still some ambiguity around naming conventions, see+<https://github.com/GaloisInc/parameterized-utils/issues/23 issue 23>.+-}++{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE Safe #-}+{-# LANGUAGE TypeOperators #-}++module Data.Parameterized.ClassesC+ ( TestEqualityC(..)+ , OrdC(..)+ ) where++import Data.Type.Equality ((:~:)(..))+import Data.Maybe (isJust)+import Data.Parameterized.Classes (OrderingF, toOrdering)+import Data.Parameterized.Some (Some(..))++class TestEqualityC (t :: (k -> *) -> *) where+ testEqualityC :: (forall x y. f x -> f y -> Maybe (x :~: y))+ -> t f+ -> t f+ -> Bool++class TestEqualityC t => OrdC (t :: (k -> *) -> *) where+ compareC :: (forall x y. f x -> g y -> OrderingF x y)+ -> t f+ -> t g+ -> Ordering++-- | This instance demonstrates where the above class is useful: namely, in+-- types with existential quantification.+instance TestEqualityC Some where+ testEqualityC subterms (Some someone) (Some something) =+ isJust (subterms someone something)++instance OrdC Some where+ compareC subterms (Some someone) (Some something) =+ toOrdering (subterms someone something)
+ src/Data/Parameterized/Compose.hs view
@@ -0,0 +1,46 @@+{-|+Description : utilities for working with "Data.Functor.Compose"+Copyright : (c) Galois, Inc 2014-2019+Maintainer : Langston Barrett <langston@galois.com>++Utilities for working with "Data.Functor.Compose".++NB: This module contains an orphan instance. It will be included in GHC 8.10,+see https://gitlab.haskell.org/ghc/ghc/merge_requests/273.+-}++{-# LANGUAGE GADTs #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE Safe #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+module Data.Parameterized.Compose+ ( testEqualityComposeBare+ ) where++import Data.Functor.Compose+import Data.Type.Equality++-- | The deduction (via generativity) that if @g x :~: g y@ then @x :~: y@.+--+-- See https://gitlab.haskell.org/ghc/ghc/merge_requests/273.+testEqualityComposeBare :: forall (f :: k -> *) (g :: l -> k) x y.+ (forall w z. f w -> f z -> Maybe (w :~: z))+ -> Compose f g x+ -> Compose f g y+ -> Maybe (x :~: y)+testEqualityComposeBare testEquality_ (Compose x) (Compose y) =+ case (testEquality_ x y :: Maybe (g x :~: g y)) of+ Just Refl -> Just (Refl :: x :~: y)+ Nothing -> Nothing++testEqualityCompose :: forall (f :: k -> *) (g :: l -> k) x y. (TestEquality f)+ => Compose f g x+ -> Compose f g y+ -> Maybe (x :~: y)+testEqualityCompose = testEqualityComposeBare testEquality++instance (TestEquality f) => TestEquality (Compose f g) where+ testEquality = testEqualityCompose
src/Data/Parameterized/Context.hs view
@@ -1,7 +1,7 @@ ------------------------------------------------------------------------ -- | -- Module : Data.Parameterized.Context--- Copyright : (c) Galois, Inc 2014-16+-- Copyright : (c) Galois, Inc 2014-2019 -- Maintainer : Joe Hendrix <jhendrix@galois.com> -- -- This module reexports either "Data.Parameterized.Context.Safe"@@ -46,10 +46,13 @@ , Data.Parameterized.Context.init , Data.Parameterized.Context.last , Data.Parameterized.Context.view+ , Data.Parameterized.Context.take , forIndexM , generateSome , generateSomeM , fromList+ , traverseAndCollect+ -- * Context extension and embedding utilities , CtxEmbedding(..) , ExtendContext(..)@@ -60,6 +63,7 @@ , extendEmbeddingRightDiff , extendEmbeddingRight , extendEmbeddingBoth+ , appendEmbedding , ctxeSize , ctxeAssignment @@ -80,10 +84,12 @@ , i1of6, i2of6, i3of6, i4of6, i5of6, i6of6 ) where +import Control.Applicative (liftA2) import Control.Lens hiding (Index, (:>), Empty) import qualified Data.Vector as V import qualified Data.Vector.Mutable as MV import GHC.TypeLits (Nat, type (-))+import Data.Monoid ((<>)) import Data.Parameterized.Classes import Data.Parameterized.Some@@ -159,7 +165,7 @@ #endif ----------------------------------------------------------------------------------- | Views+-- Views -- | Return true if assignment is empty. null :: Assignment f ctx -> Bool@@ -188,10 +194,15 @@ view :: forall f ctx . Assignment f ctx -> AssignView f ctx view = viewAssign +take :: forall f ctx ctx'. Size ctx -> Size ctx' -> Assignment f (ctx <+> ctx') -> Assignment f ctx+take sz sz' asgn =+ let diff = appendDiff sz' in+ generate sz (\i -> asgn ! extendIndex' diff i)+ ----------------------------------------------------------------------------------- | Context embedding.+-- Context embedding. --- This datastructure contains a proof that the first context is+-- | This datastructure contains a proof that the first context is -- embeddable in the second. This is useful if we want to add extend -- an existing term under a larger context. @@ -255,6 +266,11 @@ extendEmbeddingRight :: CtxEmbedding ctx ctx' -> CtxEmbedding ctx (ctx' ::> tp) extendEmbeddingRight = extendEmbeddingRightDiff knownDiff +appendEmbedding :: Size ctx -> Size ctx' -> CtxEmbedding ctx (ctx <+> ctx')+appendEmbedding sz sz' = CtxEmbedding (addSize sz sz') (generate sz (extendIndex' diff))+ where+ diff = appendDiff sz'+ extendEmbeddingBoth :: forall ctx ctx' tp. CtxEmbedding ctx ctx' -> CtxEmbedding (ctx ::> tp) (ctx' ::> tp) extendEmbeddingBoth ctxe = updated & ctxeAssignment %~ flip extend (nextIndex (ctxe ^. ctxeSize)) where@@ -305,7 +321,7 @@ ----------------------------------------------------------------------------------- CurryAssignment+-- * CurryAssignment -- | This type family is used to define currying\/uncurrying operations -- on assignments. It is best understood by seeing its evaluation on@@ -346,6 +362,24 @@ where go :: Assignment f ctx -> [Some f] -> Some (Assignment f) go prev [] = Some prev go prev (Some g:next) = (go $! prev `extend` g) next+++newtype Collector m w a = Collector { runCollector :: m w }+instance Functor (Collector m w) where+ fmap _ (Collector x) = Collector x+instance (Applicative m, Monoid w) => Applicative (Collector m w) where+ pure _ = Collector (pure mempty)+ Collector x <*> Collector y = Collector (liftA2 (<>) x y)++-- | Visit each of the elements in an @Assignment@ in order+-- from left to right and collect the results using the provided @Monoid@.+traverseAndCollect ::+ (Monoid w, Applicative m) =>+ (forall tp. Index ctx tp -> f tp -> m w) ->+ Assignment f ctx ->+ m w+traverseAndCollect f =+ runCollector . traverseWithIndex (\i x -> Collector (f i x)) -------------------------------------------------------------------------------- -- Size and Index values
src/Data/Parameterized/Context/Safe.hs view
@@ -32,7 +32,6 @@ {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE InstanceSigs #-} {-# LANGUAGE GADTs #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE IncoherentInstances #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE MultiParamTypeClasses #-}@@ -60,9 +59,12 @@ , Diff , noDiff , extendRight+ , appendDiff , DiffView(..) , viewDiff , KnownDiff(..)+ , IsAppend(..)+ , diffIsAppend -- * Indexing , Index , indexVal@@ -186,6 +188,10 @@ extendRight :: Diff l r -> Diff l (r '::> tp) extendRight diff = DiffThere diff +appendDiff :: Size r -> Diff l (l <+> r)+appendDiff SizeZero = DiffHere+appendDiff (SizeSucc sz) = DiffThere (appendDiff sz)+ composeDiff :: Diff a b -> Diff b c -> Diff a c composeDiff x DiffHere = x composeDiff x (DiffThere y) = DiffThere (composeDiff x y)@@ -199,6 +205,18 @@ extSize sz DiffHere = sz extSize sz (DiffThere diff) = incSize (extSize sz diff) +-- | Proof that @r = l <+> app@ for some @app@+data IsAppend l r where+ IsAppend :: Size app -> IsAppend l (l <+> app)++-- | If @l@ is a sub-context of @r@ then extract out their "contextual+-- difference", i.e., the @app@ such that @r = l <+> app@+diffIsAppend :: Diff l r -> IsAppend l r+diffIsAppend DiffHere = IsAppend zeroSize+diffIsAppend (DiffThere diff) =+ case diffIsAppend diff of+ IsAppend sz -> IsAppend (incSize sz)+ data DiffView a b where NoDiff :: DiffView a a ExtendRightDiff :: Diff a b -> DiffView a (b ::> r)@@ -280,9 +298,10 @@ extendIndex' DiffHere idx = idx extendIndex' (DiffThere diff) idx = IndexThere (extendIndex' diff idx) --- | Given a size @n@, an initial value @v0@, and a function @f@,--- @forIndex n v0 f@ calls @f@ on each index less than @n@ starting--- from @0@ and @v0@, with the value @v@ obtained from the last call.+-- | Given a size @n@, an initial value @v0@, and a function @f@, the+-- expression @forIndex n v0 f@ calls @f@ on each index less than @n@+-- starting from @0@ and @v0@, with the value @v@ obtained from the+-- last call. forIndex :: forall ctx r . Size ctx -> (forall tp . r -> Index ctx tp -> r)@@ -321,9 +340,10 @@ forIndexRangeImpl i (SizeSucc sz) d f r = forIndexRangeImpl (i-1) sz (LDiffThere d) f r --- | Given an index 'i', size 'n', a function 'f', value 'v', and a function 'f',--- 'forIndex i n f v' is equivalent to 'v' when 'i >= sizeInt n', and--- 'f i (forIndexRange (i+1) n v0)' otherwise.+-- | Given an index @i@, size @n@, a function @f@, value @v@, and a+-- function @f@, the expression @forIndexRange i n f v@ is equivalent+-- to @v@ when @i >= sizeInt n@, and @f i (forIndexRange (i+1) n v)@+-- otherwise. forIndexRange :: Int -> Size ctx -> (forall tp . Index ctx tp -> r -> r)@@ -409,7 +429,7 @@ replicate :: Size ctx -> (forall tp . f tp) -> Assignment f ctx replicate n c = generate n (\_ -> c) --- | Create empty indexec vector.+-- | Create empty indexed vector. empty :: Assignment f 'EmptyCtx empty = AssignmentEmpty
src/Data/Parameterized/Context/Unsafe.hs view
@@ -1,6 +1,5 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE DataKinds #-}-{-# LANGUAGE EmptyDataDecls #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE InstanceSigs #-} {-# LANGUAGE GADTs #-}@@ -32,9 +31,12 @@ , Diff , noDiff , extendRight+ , appendDiff , DiffView(..) , viewDiff , KnownDiff(..)+ , IsAppend(..)+ , diffIsAppend -- * Indexing , Index , indexVal@@ -147,6 +149,8 @@ newtype Diff (l :: Ctx k) (r :: Ctx k) = Diff { _contextExtSize :: Int } +type role Diff nominal nominal+ -- | The identity difference. noDiff :: Diff l l noDiff = Diff 0@@ -155,6 +159,9 @@ extendRight :: Diff l r -> Diff l (r '::> tp) extendRight (Diff i) = Diff (i+1) +appendDiff :: Size r -> Diff l (l <+> r)+appendDiff (Size r) = Diff r+ instance Cat.Category Diff where id = Diff 0 Diff j . Diff i = Diff (i + j)@@ -168,6 +175,15 @@ addSize (Size x) (Size y) = Size (x + y) +-- | Proof that @r = l <+> app@ for some @app@+data IsAppend l r where+ IsAppend :: Size app -> IsAppend l (l <+> app)++-- | If @l@ is a sub-context of @r@ then extract out their "contextual+-- difference", i.e., the @app@ such that @r = l <+> app@+diffIsAppend :: Diff l r -> IsAppend l r+diffIsAppend (Diff i) = unsafeCoerce $ IsAppend (Size i)+ data DiffView a b where NoDiff :: DiffView a a ExtendRightDiff :: Diff a b -> DiffView a (b ::> r)@@ -240,8 +256,9 @@ extendIndex' :: Diff l r -> Index l tp -> Index r tp extendIndex' _ = unsafeCoerce --- | Given a size 'n', an initial value 'v0', and a function 'f', 'forIndex n v0 f'--- is equivalent to 'v0' when 'n' is zero, and 'f (forIndex (n-1) v0) (n-1)' otherwise.+-- | Given a size @n@, an initial value @v0@, and a function @f@, the+-- expression @forIndex n v0 f@ is equivalent to @v0@ when @n@ is+-- zero, and @f (forIndex (n-1) v0) (n-1)@ otherwise. forIndex :: forall ctx r . Size ctx -> (forall tp . r -> Index ctx tp -> r)@@ -252,9 +269,10 @@ ZeroSize -> r IncSize p -> f (forIndex p (coerce f) r) (nextIndex p) --- | Given an index 'i', size 'n', a function 'f', value 'v', and a function 'f',--- 'forIndex i n f v' is equivalent to 'v' when 'i >= sizeInt n', and--- 'f i (forIndexRange (i+1) n v0)' otherwise.+-- | Given an index @i@, size @n@, a function @f@, value @v@, and a+-- function @f@, the expression @forIndex i n f v@ is equivalent to+-- @v@ when @i >= sizeInt n@, and @f i (forIndexRange (i+1) n v)@+-- otherwise. forIndexRange :: forall ctx r . Int -> Size ctx@@ -291,11 +309,11 @@ indexOfRange :: IndexRange ctx (EmptyCtx ::> e) -> Index ctx e indexOfRange (IndexRange i n) = assert (n == 1) $ Index i --- | `dropTailRange r n` drops the last `n` elements in `r`.+-- | @dropTailRange r n@ drops the last @n@ elements in @r@. dropTailRange :: IndexRange ctx (x <+> y) -> Size y -> IndexRange ctx x dropTailRange (IndexRange i n) (Size j) = assert (n >= j) $ IndexRange i (n - j) --- | `dropHeadRange r n` drops the first `n` elements in `r`.+-- | @dropHeadRange r n@ drops the first @n@ elements in @r@. dropHeadRange :: IndexRange ctx (x <+> y) -> Size x -> IndexRange ctx y dropHeadRange (IndexRange i n) (Size j) = assert (i' >= i && n >= j) $ IndexRange i' (n - j) where i' = i + j@@ -309,7 +327,7 @@ type instance Pred ('Succ h) = h --------------------------------------------------------------------------- BalancedTree+-- * BalancedTree -- | A balanced tree where all leaves are at the same height. --@@ -459,12 +477,12 @@ BalPair <$> bal_zipWithM f x1 (unsafeCoerce y1) <*> bal_zipWithM f x2 (unsafeCoerce y2) #if !MIN_VERSION_base(4,9,0)-bal_zipWithM _ _ _ = error "ilegal args to bal_zipWithM"+bal_zipWithM _ _ _ = error "illegal args to bal_zipWithM" #endif {-# INLINABLE bal_zipWithM #-} --------------------------------------------------------------------------- BinomialTree+-- * BinomialTree data BinomialTree (h::Height) (f :: k -> Type) :: Ctx k -> Type where Empty :: BinomialTree h f EmptyCtx@@ -605,7 +623,7 @@ -> f y -> DropResult f (x ::> y) --- | 'bal_drop x y' returns the tree formed 'append x (init y)'+-- | @bal_drop x y@ returns the tree formed @append x (init y)@ bal_drop :: forall h f x y . BinomialTree h f x -- ^ Bina@@ -686,10 +704,10 @@ {-# INLINABLE tree_zipWithM #-} --------------------------------------------------------------------------- Assignment+-- * Assignment --- | An assignment is a sequence that maps each index with type 'tp' to--- a value of type 'f tp'.+-- | An assignment is a sequence that maps each index with type @tp@ to+-- a value of type @f tp@. -- -- This assignment implementation uses a binomial tree implementation -- that offers lookups and updates in time and space logarithmic with@@ -719,7 +737,7 @@ where r = unsafe_bin_generate (sizeInt n) 0 f {-# NOINLINE generate #-} --- | Generate an assignment+-- | Generate an assignment in an 'Applicative' context generateM :: Applicative m => Size ctx -> (forall tp . Index ctx tp -> m (f tp))@@ -813,7 +831,7 @@ unsafeUpdate :: Int -> Assignment f ctx -> f u -> Assignment f ctx' unsafeUpdate i (Assignment a) e = Assignment (runIdentity (unsafe_bin_adjust (\_ -> Identity e) a i 0)) --- | View an assignment as either empty or an assignment with one appended.+-- | Represent an assignment as either empty or an assignment with one appended. data AssignView f ctx where AssignEmpty :: AssignView f EmptyCtx AssignExtend :: Assignment f ctx
src/Data/Parameterized/Ctx.hs view
@@ -1,6 +1,6 @@ {-| Description : Type-level lists.-Copyright : (c) Galois, Inc 2015+Copyright : (c) Galois, Inc 2015-2019 Maintainer : Joe Hendrix <jhendrix@galois.com> This module defines type-level lists used for representing the type of
src/Data/Parameterized/Ctx/Proofs.hs view
@@ -1,6 +1,7 @@ {-|-Copyright : (c) Galois, Inc 2015-Maintainer : Joe Hendrix <jhendrix@galois.com>+Description : type-level proofs involving contexts+Copyright : (c) Galois, Inc 2015-2019+Maintainer : Joe Hendrix <jhendrix@galois.com> This reflects type level proofs involving contexts. -}
+ src/Data/Parameterized/DecidableEq.hs view
@@ -0,0 +1,38 @@+{-|+Description : Decideable equality (i.e. evidence of non-equality) on type families+Copyright : (c) Galois, Inc 2014-2019+Maintainer : Langston Barrett <langston@galois.com>++This defines a class @DecidableEq@, which represents decidable equality on a+type family.++This is different from GHC's @TestEquality@ in that it provides evidence+of non-equality. In fact, it is a superclass of @TestEquality@.+-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE TypeInType #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE Safe #-}+module Data.Parameterized.DecidableEq+ ( DecidableEq(..)+ ) where++import Data.Void (Void)+import Data.Type.Equality ((:~:))++-- | Decidable equality.+class DecidableEq f where+ decEq :: f a -> f b -> Either (a :~: b) ((a :~: b) -> Void)++-- TODO: instances for sums, products of types with decidable equality++-- import Data.Type.Equality ((:~:), TestEquality(..))+-- instance (DecidableEq f) => TestEquality f where+-- testEquality a b =+-- case decEq a b of+-- Left prf -> Just prf+-- Right _ -> Nothing
src/Data/Parameterized/HashTable.hs view
@@ -1,13 +1,14 @@ ------------------------------------------------------------------------ -- | -- Module : Data.Parameterized.HashTable--- Copyright : (c) Galois, Inc 2014+-- Description : a hash table for parameterized keys and values+-- Copyright : (c) Galois, Inc 2014-2019 -- Maintainer : Joe Hendrix <jhendrix@galois.com> ----- This module provides a ST-based hashtable for parameterized keys and values.+-- This module provides a 'ST'-based hashtable for parameterized keys and values. ----- NOTE: This API makes use of unsafeCoerce to implement the parameterized--- hashtable abstraction. This should be typesafe provided the+-- NOTE: This API makes use of 'unsafeCoerce' to implement the parameterized+-- hashtable abstraction. This should be type-safe provided that the -- 'TestEquality' instance on the key type is implemented soundly. ------------------------------------------------------------------------ {-# LANGUAGE KindSignatures #-}
src/Data/Parameterized/List.hs view
@@ -1,10 +1,11 @@ {-|-Copyright : (c) Galois, Inc 2017-Maintainer : Joe Hendrix <jhendrix@galois.com>+Description : A type-indexed parameterized list+Copyright : (c) Galois, Inc 2017-2019+Maintainer : Joe Hendrix <jhendrix@galois.com> This module defines a list over two parameters. The first is a fixed type-level function @k -> *@ for some kind @k@, and the-second is a list of types with kind k that provide the indices for+second is a list of types with kind @k@ that provide the indices for the values in the list. This type is closely related to the @Context@ type in@@ -99,7 +100,7 @@ knownRepr = knownRepr :< knownRepr ----------------------------------------------------------------------------------- Indexed operations+-- * Indexed operations -- | Represents an index into a type-level list. Used in place of integers to
src/Data/Parameterized/Map.hs view
@@ -1,5 +1,6 @@ {-|-Copyright : (c) Galois, Inc 2014-2017+Description : Finite maps with parameterized key and value types+Copyright : (c) Galois, Inc 2014-2019 This module defines finite maps where the key and value types are parameterized by an arbitrary kind.@@ -8,17 +9,14 @@ -} {-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE FunctionalDependencies #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE InstanceSigs #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE PatternGuards #-} {-# LANGUAGE PolyKinds #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeOperators #-}-{-# LANGUAGE ViewPatterns #-} {-# LANGUAGE Trustworthy #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeInType #-}@@ -45,13 +43,21 @@ , fromKeys , fromKeysM -- * Filter+ , filter+ , filterWithKey , filterGt , filterLt -- * Folds+ , foldlWithKey+ , foldlWithKey' , foldrWithKey- -- * Traversal+ , foldrWithKey'+ , foldMapWithKey+ -- * Traversals , map+ , mapWithKey , mapMaybe+ , mapMaybeWithKey , traverseWithKey , traverseWithKey_ -- * Complex interface.@@ -65,18 +71,18 @@ , Pair(..) ) where -import Control.Applicative hiding (empty)-import Control.Lens (Traversal', Lens')-import Control.Monad.Identity-import Data.List (intercalate, foldl')-import Data.Maybe ()-import Data.Kind(Type)+import Control.Applicative hiding (empty)+import Control.Lens (Traversal', Lens')+import Control.Monad.Identity+import Data.Kind (Type)+import Data.List (intercalate, foldl')+import Data.Monoid -import Data.Parameterized.Classes-import Data.Parameterized.Some-import Data.Parameterized.Pair ( Pair(..) )-import Data.Parameterized.TraversableF-import Data.Parameterized.Utils.BinTree+import Data.Parameterized.Classes+import Data.Parameterized.Some+import Data.Parameterized.Pair ( Pair(..) )+import Data.Parameterized.TraversableF+import Data.Parameterized.Utils.BinTree ( MaybeS(..) , fromMaybeS , Updated(..)@@ -91,13 +97,13 @@ import qualified Data.Parameterized.Utils.BinTree as Bin #if MIN_VERSION_base(4,8,0)-import Prelude hiding (lookup, map, traverse, null)+import Prelude hiding (filter, lookup, map, traverse, null) #else-import Prelude hiding (lookup, map, null)+import Prelude hiding (filter, lookup, map, null) #endif --------------------------------------------------------------------------- Pair+-- * Pair comparePairKeys :: OrdF k => Pair k a -> Pair k a -> Ordering comparePairKeys (Pair x _) (Pair y _) = toOrdering (compareF x y)@@ -106,7 +112,7 @@ ------------------------------------------------------------------------ -- MapF --- | A map from parameterized keys to values with the same paramter type.+-- | A map from parameterized keys to values with the same parameter type. data MapF (k :: v -> Type) (a :: v -> Type) where Bin :: {-# UNPACK #-} !Size -- Number of elements in tree.@@ -146,7 +152,7 @@ x == y = size x == size y && toList x == toList y --------------------------------------------------------------------------- Traversals+-- * Traversals #ifdef __GLASGOW_HASKELL__ {-# NOINLINE [1] map #-}@@ -165,18 +171,30 @@ #-} #endif ++-- | Apply function to all elements in map.+mapWithKey+ :: (forall tp . ktp tp -> f tp -> g tp)+ -> MapF ktp f+ -> MapF ktp g+mapWithKey _ Tip = Tip+mapWithKey f (Bin sx kx x l r) = Bin sx kx (f kx x) (mapWithKey f l) (mapWithKey f r)+ -- | Modify elements in a map map :: (forall tp . f tp -> g tp) -> MapF ktp f -> MapF ktp g-map _ Tip = Tip-map f (Bin sx kx x l r) = Bin sx kx (f x) (map f l) (map f r)+map f = mapWithKey (\_ x -> f x) --- | Run partial map over elements.+-- | Map keys and elements and collect `Just` results.+mapMaybeWithKey :: (forall tp . k tp -> f tp -> Maybe (g tp)) -> MapF k f -> MapF k g+mapMaybeWithKey _ Tip = Tip+mapMaybeWithKey f (Bin _ k x l r) =+ case f k x of+ Just y -> Bin.link (Pair k y) (mapMaybeWithKey f l) (mapMaybeWithKey f r)+ Nothing -> Bin.merge (mapMaybeWithKey f l) (mapMaybeWithKey f r)++-- | Map elements and collect `Just` results. mapMaybe :: (forall tp . f tp -> Maybe (g tp)) -> MapF ktp f -> MapF ktp g-mapMaybe _ Tip = Tip-mapMaybe f (Bin _ k x l r) =- case f x of- Just y -> Bin.link (Pair k y) (mapMaybe f l) (mapMaybe f r)- Nothing -> Bin.merge (mapMaybe f l) (mapMaybe f r)+mapMaybe f = mapMaybeWithKey (\_ x -> f x) -- | Traverse elements in a map traverse :: Applicative m => (forall tp . f tp -> m (g tp)) -> MapF ktp f -> m (MapF ktp g)@@ -270,13 +288,43 @@ elems :: MapF k a -> [Some a] elems = foldrF (\e l -> Some e : l) [] --- | Perform a fold with the key also provided.+-- | Perform a left fold with the key also provided.+foldlWithKey :: (forall s . b -> k s -> a s -> b) -> b -> MapF k a -> b+foldlWithKey _ z Tip = z+foldlWithKey f z (Bin _ kx x l r) =+ let lz = foldlWithKey f z l+ kz = f lz kx x+ in foldlWithKey f kz r++-- | Perform a strict left fold with the key also provided.+foldlWithKey' :: (forall s . b -> k s -> a s -> b) -> b -> MapF k a -> b+foldlWithKey' _ z Tip = z+foldlWithKey' f z (Bin _ kx x l r) =+ let lz = foldlWithKey f z l+ kz = seq lz $ f lz kx x+ in seq kz $ foldlWithKey f kz r++-- | Perform a right fold with the key also provided. foldrWithKey :: (forall s . k s -> a s -> b -> b) -> b -> MapF k a -> b-foldrWithKey f z = go z- where- go z' Tip = z'- go z' (Bin _ kx x l r) = go (f kx x (go z' r)) l+foldrWithKey _ z Tip = z+foldrWithKey f z (Bin _ kx x l r) =+ let rz = foldrWithKey f z r+ kz = f kx x rz+ in foldrWithKey f kz l +-- | Perform a strict right fold with the key also provided.+foldrWithKey' :: (forall s . k s -> a s -> b -> b) -> b -> MapF k a -> b+foldrWithKey' _ z Tip = z+foldrWithKey' f z (Bin _ kx x l r) =+ let rz = foldrWithKey f z r+ kz = seq rz $ f kx x rz+ in seq kz $ foldrWithKey f kz l++-- | Fold the keys and values using the given monoid.+foldMapWithKey :: Monoid m => (forall s . k s -> a s -> m) -> MapF k a -> m+foldMapWithKey _ Tip = mempty+foldMapWithKey f (Bin _ kx x l r) = foldMapWithKey f l <> f kx x <> foldMapWithKey f r+ showMap :: (forall tp . ktp tp -> String) -> (forall tp . rtp tp -> String) -> MapF ktp rtp@@ -287,6 +335,17 @@ ------------------------------------------------------------------------ -- filter +-- | Return entries with values that satisfy a predicate.+filter :: (forall tp . f tp -> Bool) -> MapF k f -> MapF k f+filter f = filterWithKey (\_ v -> f v)++-- | Return key-value pairs that satisfy a predicate.+filterWithKey :: (forall tp . k tp -> f tp -> Bool) -> MapF k f -> MapF k f+filterWithKey _ Tip = Tip+filterWithKey f (Bin _ k x l r)+ | f k x = Bin.link (Pair k x) (filterWithKey f l) (filterWithKey f r)+ | otherwise = Bin.merge (filterWithKey f l) (filterWithKey f r)+ compareKeyPair :: OrdF k => k tp -> Pair k a -> Ordering compareKeyPair k = \(Pair x _) -> toOrdering (compareF k x) @@ -331,9 +390,9 @@ -- | @insertWith f new m@ inserts the binding into @m@. ----- It inserts @f new old@ if @m@ already contains an equivaltn value--- @old@, and @new@ otherwise. It returns an Unchanged value if the--- map stays the same size and an updated value if a new entry was+-- It inserts @f new old@ if @m@ already contains an equivalent value+-- @old@, and @new@ otherwise. It returns an 'Unchanged' value if the+-- map stays the same size and an 'Updated' value if a new entry was -- inserted. insertWith :: OrdF k => (a tp -> a tp -> a tp) -> k tp -> a tp -> MapF k a -> MapF k a insertWith = \f k v t -> seq k $ updatedValue (insertWithImpl f k v t)@@ -356,7 +415,7 @@ ------------------------------------------------------------------------ -- updateAtKey --- | Update request tells when to do with value+-- | 'UpdateRequest' tells what to do with a found value data UpdateRequest v = -- | Keep the current value. Keep@@ -443,9 +502,9 @@ fromKeysM :: forall m (t :: Type -> Type) (a :: k -> Type) (v :: k -> Type) . (Monad m, Foldable t, OrdF a) => (forall tp . a tp -> m (v tp))- -- ^ Function for evaluating a register value.+ -- ^ Function for evaluating an input value to store the result in the map. -> t (Some a)- -- ^ Set of X86 registers+ -- ^ Set of input values (traversed via folding) -> m (MapF a v) fromKeysM f = foldM go empty where go :: MapF a v -> Some a -> m (MapF a v)
src/Data/Parameterized/NatRepr.hs view
@@ -1,21 +1,26 @@ {-|-Copyright : (c) Galois, Inc 2014-2015-Maintainer : Joe Hendrix <jhendrix@galois.com>+Description : Type level natural number representation at runtime+Copyright : (c) Galois, Inc 2014-2019+Maintainer : Joe Hendrix <jhendrix@galois.com> This defines a type 'NatRepr' for representing a type-level natural at runtime. This can be used to branch on a type-level value. For-each @n@, @NatRepr n@ contains a single value containing the vlaue+each @n@, @NatRepr n@ contains a single value containing the value @n@. This can be used to help use type-level variables on code with data dependendent types. -The 'TestEquality' instance for 'NatRepr' is implemented using-'unsafeCoerce', as is the `isZeroNat` function. This should be-typesafe because we maintain the invariant that the integer value+The @TestEquality@ and @DecidableEq@ instances for 'NatRepr'+are implemented using 'unsafeCoerce', as is the `isZeroNat` function. This+should be typesafe because we maintain the invariant that the integer value contained in a NatRepr value matches its static type. -} {-# LANGUAGE CPP #-} {-# LANGUAGE DataKinds #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE EmptyCase #-}+{-# LANGUAGE EmptyDataDecls #-} {-# LANGUAGE ExplicitNamespaces #-}+{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-}@@ -24,19 +29,25 @@ {-# LANGUAGE TypeOperators #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE RankNTypes #-}+{-# LANGUAGE RoleAnnotations #-} {-# LANGUAGE PatternGuards #-} {-# LANGUAGE Trustworthy #-} {-# LANGUAGE TypeApplications #-} #if MIN_VERSION_base(4,9,0) {-# OPTIONS_GHC -fno-warn-redundant-constraints #-} #endif+#if __GLASGOW_HASKELL__ >= 805+{-# LANGUAGE NoStarIsType #-}+#endif module Data.Parameterized.NatRepr ( NatRepr , natValue+ , intValue , knownNat , withKnownNat , IsZeroNat(..) , isZeroNat+ , isZeroOrGT1 , NatComparison(..) , compareNat , decNat@@ -49,11 +60,18 @@ , withDivModNat , natMultiply , someNat+ , mkNatRepr , maxNat , natRec+ , natRecStrong+ , natRecBounded , natForEach+ , natFromZero , NatCases(..) , testNatCases+ -- * Strict order+ , lessThanIrreflexive+ , lessThanAsymmetric -- * Bitvector utilities , widthVal , minUnsigned@@ -66,6 +84,7 @@ , signedClamp -- * LeqProof , LeqProof(..)+ , decideLeq , testLeq , testStrictLeq , leqRefl@@ -98,6 +117,7 @@ , withSubMulDistribRight , mulCancelR , mul2Plus+ , lemmaMul -- * Re-exports typelists basics -- , NatK , type (+)@@ -109,92 +129,35 @@ , Data.Parameterized.Some.Some ) where -import Data.Bits ((.&.))-import Data.Hashable-import Data.Proxy as Proxy+import Data.Bits ((.&.), bit)+import Data.Data import Data.Type.Equality as Equality-import GHC.TypeLits as TypeLits+import Data.Void as Void+import Numeric.Natural+import GHC.TypeNats as TypeNats import Unsafe.Coerce -import Data.Parameterized.Classes+import Data.Parameterized.NatRepr.Internal import Data.Parameterized.Some -maxInt :: Integer-maxInt = toInteger (maxBound :: Int)----------------------------------------------------------------------------- Nat+maxInt :: Natural+maxInt = fromIntegral (maxBound :: Int) --- | A runtime presentation of a type-level 'Nat'.------ This can be used for performing dynamic checks on a type-level natural--- numbers.-newtype NatRepr (n::Nat) = NatRepr { natValue :: Integer- -- ^ The underlying integer value of the number.- }- deriving (Hashable)+intValue :: NatRepr n -> Integer+intValue n = toInteger (natValue n)+{-# INLINE intValue #-} -- | Return the value of the nat representation. widthVal :: NatRepr n -> Int-widthVal (NatRepr i) | i < maxInt = fromInteger i- | otherwise = error "Width is too large."--instance Eq (NatRepr m) where- _ == _ = True--instance TestEquality NatRepr where- testEquality (NatRepr m) (NatRepr n)- | m == n = Just (unsafeCoerce Refl)- | otherwise = Nothing---- | Result of comparing two numbers.-data NatComparison m n where- -- First number is less than second.- NatLT :: x+1 <= x+(y+1) => !(NatRepr y) -> NatComparison x (x+(y+1))- NatEQ :: NatComparison x x- -- First number is greater than second.- NatGT :: x+1 <= x+(y+1) => !(NatRepr y) -> NatComparison (x+(y+1)) x--compareNat :: NatRepr m -> NatRepr n -> NatComparison m n-compareNat m n =- case compare (natValue m) (natValue n) of- LT -> unsafeCoerce (NatLT @0 @0) (NatRepr (natValue n - natValue m - 1))- EQ -> unsafeCoerce NatEQ- GT -> unsafeCoerce (NatGT @0 @0) (NatRepr (natValue m - natValue n - 1))--instance OrdF NatRepr where- compareF x y =- case compareNat x y of- NatLT _ -> LTF- NatEQ -> EQF- NatGT _ -> GTF--instance PolyEq (NatRepr m) (NatRepr n) where- polyEqF x y = fmap (\Refl -> Refl) $ testEquality x y--instance Show (NatRepr n) where- show (NatRepr n) = show n--instance ShowF NatRepr--instance HashableF NatRepr where- hashWithSaltF = hashWithSalt---- | This generates a NatRepr from a type-level context.-knownNat :: forall n . KnownNat n => NatRepr n-knownNat = NatRepr (natVal (Proxy :: Proxy n))--instance (KnownNat n) => KnownRepr NatRepr n where- knownRepr = knownNat+widthVal (NatRepr i) | i <= maxInt = fromIntegral i+ | otherwise = error ("Width is too large: " ++ show i) -{-# DEPRECATED withKnownNat "This function is potentially unsafe and is schedueled to be removed." #-} withKnownNat :: forall n r. NatRepr n -> (KnownNat n => r) -> r withKnownNat (NatRepr nVal) v = case someNatVal nVal of- Just (SomeNat (Proxy :: Proxy n')) ->- case unsafeCoerce (Refl :: 0 :~: 0) :: n :~: n' of+ SomeNat (Proxy :: Proxy n') ->+ case unsafeCoerce (Refl :: n :~: n) :: n :~: n' of Refl -> v- Nothing -> error "withKnownNat: inner value in NatRepr is not a natural" data IsZeroNat n where ZeroNat :: IsZeroNat 0@@ -204,11 +167,35 @@ isZeroNat (NatRepr 0) = unsafeCoerce ZeroNat isZeroNat (NatRepr _) = unsafeCoerce NonZeroNat +-- | Every nat is either zero or >= 1.+isZeroOrGT1 :: NatRepr n -> Either (n :~: 0) (LeqProof 1 n)+isZeroOrGT1 n =+ case isZeroNat n of+ ZeroNat -> Left Refl+ NonZeroNat -> Right $+ -- We have n = m + 1 for some m.+ let+ -- | x <= x + 1+ leqSucc:: forall x. LeqProof x (x+1)+ leqSucc = leqAdd2 (LeqProof :: LeqProof x x) (LeqProof :: LeqProof 0 1)+ leqPlus :: forall f x y. ((x + 1) ~ y) => f x -> LeqProof 1 y+ leqPlus fx =+ case (plusComm fx (knownNat @1) :: x + 1 :~: 1 + x) of { Refl ->+ case (plusMinusCancel (knownNat @1) fx :: 1+x-x :~: 1) of { Refl ->+ case (LeqProof :: LeqProof (x+1) y) of { LeqProof ->+ case (LeqProof :: LeqProof (1+x-x) (y-x)) of { LeqProof ->+ leqTrans (LeqProof :: LeqProof 1 (y-x))+ (leqSub (LeqProof :: LeqProof y y)+ (leqTrans (leqSucc :: LeqProof x (x+1))+ (LeqProof) :: LeqProof x y) :: LeqProof (y - x) y)+ }}}}+ in leqPlus (predNat n)+ -- | Decrement a @NatRepr@ decNat :: (1 <= n) => NatRepr n -> NatRepr (n-1) decNat (NatRepr i) = NatRepr (i-1) --- | Get the predicessor of a nat+-- | Get the predecessor of a nat predNat :: NatRepr (n+1) -> NatRepr n predNat (NatRepr i) = NatRepr (i-1) @@ -254,15 +241,15 @@ -- | Return maximum unsigned value for bitvector with given width. maxUnsigned :: NatRepr w -> Integer-maxUnsigned w = 2^(natValue w) - 1+maxUnsigned w = bit (widthVal w) - 1 --- | Return minimum value for bitvector in 2s complement with given width.+-- | Return minimum value for bitvector in two's complement with given width. minSigned :: (1 <= w) => NatRepr w -> Integer-minSigned w = negate (2^(natValue w - 1))+minSigned w = negate (bit (widthVal w - 1)) --- | Return maximum value for bitvector in 2s complement with given width.+-- | Return maximum value for bitvector in two's complement with given width. maxSigned :: (1 <= w) => NatRepr w -> Integer-maxSigned w = 2^(natValue w - 1) - 1+maxSigned w = bit (widthVal w - 1) - 1 -- | @toUnsigned w i@ maps @i@ to a @i `mod` 2^w@. toUnsigned :: NatRepr w -> Integer -> Integer@@ -272,7 +259,7 @@ -- signed number in two's complement notation and returns that value. toSigned :: (1 <= w) => NatRepr w -> Integer -> Integer toSigned w i0- | i > maxSigned w = i - 2^(natValue w)+ | i > maxSigned w = i - bit (widthVal w) | otherwise = i where i = i0 .&. maxUnsigned w @@ -295,10 +282,16 @@ ------------------------------------------------------------------------ -- Some NatRepr -someNat :: Integer -> Maybe (Some NatRepr)-someNat n | 0 <= n && n <= toInteger maxInt = Just (Some (NatRepr (fromInteger n)))- | otherwise = Nothing+-- | Turn an @Integral@ value into a @NatRepr@. Returns @Nothing@+-- if the given value is negative.+someNat :: Integral a => a -> Maybe (Some NatRepr)+someNat x | x >= 0 = Just . Some . NatRepr $! fromIntegral x+someNat _ = Nothing +-- | Turn a @Natural@ into the corresponding @NatRepr@+mkNatRepr :: Natural -> Some NatRepr+mkNatRepr n = Some (NatRepr n)+ -- | Return the maximum of two nat representations. maxNat :: NatRepr m -> NatRepr n -> Some NatRepr maxNat x y@@ -308,11 +301,11 @@ ------------------------------------------------------------------------ -- Arithmetic --- | Produce evidence that + is commutative.+-- | Produce evidence that @+@ is commutative. plusComm :: forall f m g n . f m -> g n -> m+n :~: n+m plusComm _ _ = unsafeCoerce (Refl :: m+n :~: m+n) --- | Produce evidence that * is commutative.+-- | Produce evidence that @*@ is commutative. mulComm :: forall f m g n. f m -> g n -> (m * n) :~: (n * m) mulComm _ _ = unsafeCoerce Refl @@ -320,7 +313,7 @@ mul2Plus n = case addMulDistribRight (Proxy @1) (Proxy @1) n of Refl -> Refl --- | Cancel an add followed b a subtract+-- | Cancel an add followed by a subtract plusMinusCancel :: forall f m g n . f m -> g n -> (m + n) - n :~: m plusMinusCancel _ _ = unsafeCoerce (Refl :: m :~: m) @@ -345,8 +338,6 @@ case unsafeCoerce (Refl :: 0 :~: 0) of (Refl :: (((n * p) - (m * p)) :~: ((n - m) * p)) ) -> f -- ------------------------------------------------------------------------ -- LeqProof @@ -355,6 +346,13 @@ data LeqProof m n where LeqProof :: (m <= n) => LeqProof m n +-- | (<=) is a decidable relation on nats.+decideLeq :: NatRepr a -> NatRepr b -> Either (LeqProof a b) ((LeqProof a b) -> Void)+decideLeq (NatRepr m) (NatRepr n)+ | m <= n = Left $ unsafeCoerce (LeqProof :: LeqProof 0 0)+ | otherwise = Right $+ \x -> seq x $ error "Impossible [decidable <= on NatRepr]"+ testStrictLeq :: forall m n . (m <= n) => NatRepr m@@ -384,6 +382,31 @@ GT -> NatCaseGT (unsafeCoerce (LeqProof :: LeqProof 0 0)) {-# NOINLINE testNatCases #-} +-- | The strict order (<), defined by n < m <-> n + 1 <= m, is irreflexive.+lessThanIrreflexive :: forall f (a :: Nat). f a -> LeqProof (1 + a) a -> Void+lessThanIrreflexive a prf =+ let prf1 :: LeqProof (1 + a - a) (a - a)+ prf1 = leqSub2 prf (LeqProof :: LeqProof a a)+ prf2 :: 1 + a - a :~: 1+ prf2 = plusMinusCancel (knownNat @1) a+ prf3 :: a - a :~: 0+ prf3 = plusMinusCancel (knownNat @0) a+ prf4 :: LeqProof 1 0+ prf4 = case prf2 of Refl -> case prf3 of { Refl -> prf1 }+ in case prf4 of {}++-- | The strict order on the naturals is irreflexive.+lessThanAsymmetric :: forall m f n+ . LeqProof (n+1) m+ -> LeqProof (m+1) n+ -> f n+ -> Void+lessThanAsymmetric nLTm mLTn n =+ case plusComm n (knownNat @1) :: n + 1 :~: 1 + n of { Refl ->+ case leqAdd (LeqProof :: LeqProof m m) (knownNat @1) :: LeqProof m (m+1) of+ LeqProof -> lessThanIrreflexive n $ leqTrans (leqTrans nLTm LeqProof) mLTn+ }+ -- | @x `testLeq` y@ checks whether @x@ is less than or equal to @y@. testLeq :: forall m n . NatRepr m -> NatRepr n -> Maybe (LeqProof m n) testLeq (NatRepr m) (NatRepr n)@@ -395,7 +418,6 @@ leqRefl :: forall f n . f n -> LeqProof n n leqRefl _ = LeqProof - -- | Apply transitivity to LeqProof leqTrans :: LeqProof m n -> LeqProof n p -> LeqProof m p leqTrans LeqProof LeqProof = unsafeCoerce (LeqProof :: LeqProof 0 0)@@ -509,19 +531,84 @@ -> [a] natForEach l h f = natForEach' l h (\LeqProof LeqProof -> f) +-- | Apply a function to each element in a range starting at zero;+-- return the list of values obtained.+natFromZero :: forall h a+ . NatRepr h+ -> (forall n. (n <= h) => NatRepr n -> a)+ -> [a]+natFromZero = natForEach (knownNat @0)+ -- | Recursor for natural numbeers.-natRec :: forall m f- . NatRepr m- -> f 0+natRec :: forall p f+ . NatRepr p+ -> f 0 {- ^ base case -} -> (forall n. NatRepr n -> f n -> f (n + 1))- -> f m-natRec n f0 ih = go n- where- go :: forall n'. NatRepr n' -> f n'- go n' = case isZeroNat n' of- ZeroNat -> f0- NonZeroNat -> let n'' = predNat n' in ih n'' (go n'')+ -> f p+natRec n base ind =+ case isZeroNat n of+ ZeroNat -> base+ NonZeroNat -> let n' = predNat n+ in ind n' (natRec n' base ind) +-- | Strong induction variant of the recursor.+natRecStrong :: forall p f+ . NatRepr p+ -> f 0 {- ^ base case -}+ -> (forall n.+ NatRepr n ->+ (forall m. (m <= n) => NatRepr m -> f m) ->+ f (n + 1)) {- ^ inductive step -}+ -> f p+natRecStrong p base ind = natRecStrong' base ind p+ where -- We can't use use "flip" or some other basic combinator+ -- because type variables can't be instantiated to contain "forall"s.+ natRecStrong' :: forall p' f'+ . f' 0 {- ^ base case -}+ -> (forall n.+ NatRepr n ->+ (forall m. (m <= n) => NatRepr m -> f' m) ->+ f' (n + 1)) {- ^ inductive step -}+ -> NatRepr p'+ -> f' p'+ natRecStrong' base' ind' n =+ case isZeroNat n of+ ZeroNat -> base'+ NonZeroNat -> ind' (predNat n) (natRecStrong' base' ind')++-- | Bounded recursor for natural numbers.+--+-- If you can prove:+-- - Base case: f 0+-- - Inductive step: if n <= h and (f n) then (f (n + 1))+-- You can conclude: for all n <= h, (f (n + 1)).+natRecBounded :: forall m h f. (m <= h)+ => NatRepr m+ -> NatRepr h+ -> f 0+ -> (forall n. (n <= h) => NatRepr n -> f n -> f (n + 1))+ -> f (m + 1)+natRecBounded m h base indH =+ case isZeroOrGT1 m of+ Left Refl -> indH (knownNat @0) base+ Right LeqProof ->+ case decideLeq m h of+ Left LeqProof {- :: m <= h -} ->+ let -- Since m is non-zero, it is n + 1 for some n.+ lemma :: LeqProof (m-1) h+ lemma = leqSub (LeqProof :: LeqProof m h) (LeqProof :: LeqProof 1 m)+ in indH m $+ case lemma of { LeqProof ->+ case minusPlusCancel m (knownNat @1) of { Refl ->+ natRecBounded @(m - 1) @h @f (predNat m) h base indH+ }}+ Right f {- :: (m <= h) -> Void -} ->+ absurd $ f (LeqProof :: LeqProof m h)+ mulCancelR :: (1 <= c, (n1 * c) ~ (n2 * c)) => f1 n1 -> f2 n2 -> f3 c -> (n1 :~: n2) mulCancelR _ _ _ = unsafeCoerce Refl++-- | Used in @Vector@+lemmaMul :: (1 <= n) => p w -> q n -> (w + (n-1) * w) :~: (n * w)+lemmaMul = unsafeCoerce Refl
+ src/Data/Parameterized/NatRepr/Internal.hs view
@@ -0,0 +1,99 @@+{-|+Copyright : (c) Galois, Inc 2014-2018+Maintainer : Joe Hendrix <jhendrix@galois.com>++This internal module exports the 'NatRepr' type and its constructor. It is intended+for use only within parameterized-utils, and is excluded from the module export list.+-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE RoleAnnotations #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeOperators #-}++module Data.Parameterized.NatRepr.Internal where++import Data.Data+import Data.Hashable+import GHC.TypeNats+import Numeric.Natural+import Unsafe.Coerce++import Data.Parameterized.Classes+import Data.Parameterized.DecidableEq++------------------------------------------------------------------------+-- Nat++-- | A runtime presentation of a type-level 'Nat'.+--+-- This can be used for performing dynamic checks on a type-level natural+-- numbers.+newtype NatRepr (n::Nat) = NatRepr { natValue :: Natural+ -- ^ The underlying natural value of the number.+ }+ deriving (Hashable, Data)++type role NatRepr nominal++instance Eq (NatRepr m) where+ _ == _ = True++instance TestEquality NatRepr where+ testEquality (NatRepr m) (NatRepr n)+ | m == n = Just (unsafeCoerce Refl)+ | otherwise = Nothing++instance DecidableEq NatRepr where+ decEq (NatRepr m) (NatRepr n)+ | m == n = Left $ unsafeCoerce Refl+ | otherwise = Right $+ \x -> seq x $ error "Impossible [DecidableEq on NatRepr]"++compareNat :: NatRepr m -> NatRepr n -> NatComparison m n+compareNat m n =+ case compare (natValue m) (natValue n) of+ LT -> unsafeCoerce (NatLT @0 @0) (NatRepr (natValue n - natValue m - 1))+ EQ -> unsafeCoerce NatEQ+ GT -> unsafeCoerce (NatGT @0 @0) (NatRepr (natValue m - natValue n - 1))++-- | Result of comparing two numbers.+data NatComparison m n where+ -- First number is less than second.+ NatLT :: x+1 <= x+(y+1) => !(NatRepr y) -> NatComparison x (x+(y+1))+ NatEQ :: NatComparison x x+ -- First number is greater than second.+ NatGT :: x+1 <= x+(y+1) => !(NatRepr y) -> NatComparison (x+(y+1)) x++instance OrdF NatRepr where+ compareF x y =+ case compareNat x y of+ NatLT _ -> LTF+ NatEQ -> EQF+ NatGT _ -> GTF++instance PolyEq (NatRepr m) (NatRepr n) where+ polyEqF x y = fmap (\Refl -> Refl) $ testEquality x y++instance Show (NatRepr n) where+ show (NatRepr n) = show n++instance ShowF NatRepr++instance HashableF NatRepr where+ hashWithSaltF = hashWithSalt++-- | This generates a NatRepr from a type-level context.+knownNat :: forall n . KnownNat n => NatRepr n+knownNat = NatRepr (natVal (Proxy :: Proxy n))++instance (KnownNat n) => KnownRepr NatRepr n where+ knownRepr = knownNat
src/Data/Parameterized/Nonce.hs view
@@ -1,12 +1,13 @@ {-|-Copyright : (c) Galois, Inc 2014-2016-Maintainer : Joe Hendrix <jhendrix@galois.com>+Description : Index generator in the ST monad.+Copyright : (c) Galois, Inc 2014-2019+Maintainer : Joe Hendrix <jhendrix@galois.com> -This module provides a simple generator of new indexes in the ST monad.+This module provides a simple generator of new indexes in the 'ST' monad. It is predictable and not intended for cryptographic purposes. This module also provides a global nonce generator that will generate-2^64 nonces before looping.+2^64 nonces before repeating. NOTE: The 'TestEquality' and 'OrdF' instances for the 'Nonce' type simply compare the generated nonce values and then assert to the compiler@@ -16,6 +17,7 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE ExistentialQuantification #-} {-# LANGUAGE EmptyDataDecls #-}+{-# LANGUAGE GADTs #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE PolyKinds #-}@@ -29,6 +31,7 @@ ( -- * NonceGenerator NonceGenerator , freshNonce+ , countNoncesGenerated , Nonce , indexValue -- * Accessing a nonce generator@@ -36,6 +39,7 @@ , newIONonceGenerator , withIONonceGenerator , withSTNonceGenerator+ -- * Global nonce generator , withGlobalSTNonceGenerator , GlobalNonceGenerator , globalNonceGenerator@@ -53,7 +57,7 @@ import Data.Parameterized.Classes import Data.Parameterized.Some -#if MIN_VERSION_base(4,9,0)+#if MIN_VERSION_base(4,9,0) && __GLASGOW_HASKELL__ < 805 import Data.Kind #endif @@ -61,55 +65,55 @@ -- -- The first type parameter @m@ is the monad used for generating names, and -- the second parameter @s@ is used for the counter.-data NonceGenerator (m :: * -> *) (s :: *) = NonceGenerator {+data NonceGenerator (m :: * -> *) (s :: *) where+ STNG :: !(STRef t Word64) -> NonceGenerator (ST t) s+ IONG :: !(IORef Word64) -> NonceGenerator IO s+ #if MIN_VERSION_base(4,9,0) -- We have to make the k explicit in GHC 8.0 to avoid a warning.- freshNonce :: forall k (tp :: k) . m (Nonce s tp)+freshNonce :: forall m s k (tp :: k) . NonceGenerator m s -> m (Nonce s tp) #else- freshNonce :: forall (tp :: k) . m (Nonce s tp)+freshNonce :: forall m s (tp :: k) . NonceGenerator m s -> m (Nonce s tp) #endif- }+freshNonce (IONG r) =+ atomicModifyIORef' r $ \n -> (n+1, Nonce n)+freshNonce (STNG r) = do+ i <- readSTRef r+ writeSTRef r $! i+1+ return $ Nonce i+ -- (Weirdly, there's no atomicModifySTRef'. Yes, only the IO monad+ -- does concurrency, but the ST monad is part of the IO monad via+ -- stToIO, so there's no guarantee that ST code won't be run in+ -- multiple threads.) --- | Create a new counter.-withGlobalSTNonceGenerator :: (forall t . NonceGenerator (ST t) t -> ST t r) -> r-withGlobalSTNonceGenerator f = runST $ do- r <- newSTRef (toEnum 0)- f $! NonceGenerator {- freshNonce = do- i <- readSTRef r- writeSTRef r $! succ i- return $! Nonce i- }+{-# INLINE freshNonce #-}+ -- Inlining is particularly necessary since there's no @Monad m@+ -- constraint on 'freshNonce', so SPECIALIZE doesn't work on it. In+ -- this case, though, we get specialization for free from inlining.+ -- For instance, a @NonceGenerator IO s@ must be an @IONG@, so the+ -- simplifier eliminates the STNG branch. --- | Create a new nonce generator in the ST monad.+-- | The number of nonces generated so far by this generator. Only+-- really useful for profiling.+countNoncesGenerated :: NonceGenerator m s -> m Integer+countNoncesGenerated (IONG r) = toInteger <$> readIORef r+countNoncesGenerated (STNG r) = toInteger <$> readSTRef r++-- | Create a new nonce generator in the 'ST' monad. newSTNonceGenerator :: ST t (Some (NonceGenerator (ST t)))-newSTNonceGenerator = g <$> newSTRef (toEnum 0)- where g r = Some $!- NonceGenerator {- freshNonce = do- i <- readSTRef r- writeSTRef r $! succ i- return $! Nonce i- }+newSTNonceGenerator = Some . STNG <$> newSTRef (toEnum 0) --- | Create a new nonce generator in the ST monad.+-- | Create a new nonce generator in the 'ST' monad. newIONonceGenerator :: IO (Some (NonceGenerator IO))-newIONonceGenerator = g <$> newIORef (toEnum 0)- where g r = Some $!- NonceGenerator {- freshNonce = do- i <- readIORef r- writeIORef r $! succ i- return $! Nonce i- }+newIONonceGenerator = Some . IONG <$> newIORef (toEnum 0) --- | Run a ST computation with a new nonce generator in the ST monad.+-- | Run a 'ST' computation with a new nonce generator in the 'ST' monad. withSTNonceGenerator :: (forall s . NonceGenerator (ST t) s -> (ST t) r) -> ST t r withSTNonceGenerator f = do Some r <- newSTNonceGenerator f r --- | Create a new nonce generator in the IO monad.+-- | Create a new nonce generator in the 'IO' monad. withIONonceGenerator :: (forall s . NonceGenerator IO s -> IO r) -> IO r withIONonceGenerator f = do Some r <- newIONonceGenerator@@ -142,7 +146,7 @@ instance ShowF (Nonce s) --------------------------------------------------------------------------- GlobalNonceGenerator+-- * GlobalNonceGenerator data GlobalNonceGenerator @@ -152,7 +156,10 @@ -- | A nonce generator that uses a globally-defined counter. globalNonceGenerator :: NonceGenerator IO GlobalNonceGenerator-globalNonceGenerator =- NonceGenerator- { freshNonce = Nonce <$> atomicModifyIORef' globalNonceIORef (\n -> (n+1, n))- }+globalNonceGenerator = IONG globalNonceIORef++-- | Create a new counter.+withGlobalSTNonceGenerator :: (forall t . NonceGenerator (ST t) t -> ST t r) -> r+withGlobalSTNonceGenerator f = runST $ do+ r <- newSTRef (toEnum 0)+ f $! STNG r
src/Data/Parameterized/Nonce/Transformers.hs view
@@ -1,6 +1,7 @@ {-|-Copyright : (c) Galois, Inc 2014-2016-Maintainer : Eddy Westbrook <westbrook@galois.com>+Description : A typeclass and monad transformers for generating nonces.+Copyright : (c) Galois, Inc 2014-2019+Maintainer : Eddy Westbrook <westbrook@galois.com> This module provides a typeclass and monad transformers for generating nonces.
src/Data/Parameterized/Pair.hs view
@@ -1,5 +1,6 @@ {-|-Copyright : (c) Galois, Inc 2017+nDescription : A 2-tuple with identically parameterized elements+Copyright : (c) Galois, Inc 2017-2019 This module defines a 2-tuple where both elements are parameterized over the same existentially quantified parameter.
+ src/Data/Parameterized/Peano.hs view
@@ -0,0 +1,501 @@+{-|+Description: Representations of a type-level natural at runtime.+Copyright : (c) Galois, Inc 2019++This defines a type 'Peano' and 'PeanoRepr' for representing a+type-level natural at runtime. These type-level numbers are defined+inductively instead of using GHC.TypeLits.++As a result, type-level computation defined recursively over these+numbers works more smoothly. (For example, see the type-level+function 'Repeat' below.)++Note: as in "NatRepr", in UNSAFE mode, the runtime representation of+these type-level natural numbers is 'Word64'.++-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE EmptyCase #-}+{-# LANGUAGE ExplicitNamespaces #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE PatternGuards #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE RoleAnnotations #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE UndecidableInstances #-}++#if MIN_VERSION_base(4,9,0)+{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}+#endif+#if __GLASGOW_HASKELL__ >= 805+{-# LANGUAGE NoStarIsType #-}+#endif+module Data.Parameterized.Peano+ ( -- * Peano+ Peano+ , Z , S++ -- * Basic arithmetic + , Plus, Minus, Mul, Max, Min+ , plusP, minusP, mulP, maxP, minP+ , zeroP, succP, predP++ -- * Counting+ , Repeat, CtxSizeP+ , repeatP, ctxSizeP+ + -- * Comparisons+ , Le, Lt, Gt, Ge+ , leP, ltP, gtP, geP++ -- * Runtime representation+ , KnownPeano+ , PeanoRepr+ , PeanoView(..), peanoView, viewRepr++ -- * 'Some Peano'+ , mkPeanoRepr, peanoValue + , somePeano+ , maxPeano+ , minPeano+ , peanoLength++ -- * Properties+ , plusCtxSizeAxiom+ , minusPlusAxiom+ , ltMinusPlusAxiom++ -- * Re-exports+ , TestEquality(..)+ , (:~:)(..)+ , Data.Parameterized.Some.Some++ ) where++import Data.Parameterized.BoolRepr+import Data.Parameterized.Classes+import Data.Parameterized.DecidableEq+import Data.Parameterized.Some+import Data.Parameterized.Context++import Data.Hashable+import Data.Word++#ifdef UNSAFE_OPS+import Unsafe.Coerce(unsafeCoerce)+#endif++------------------------------------------------------------------------+-- * Peano arithmetic++-- | Unary representation for natural numbers+data Peano = Z | S Peano+-- | Peano zero+type Z = 'Z+-- | Peano successor+type S = 'S++-- Peano numbers are more about *counting* than arithmetic.+-- They are most useful as iteration arguments and list indices+-- However, for completeness, we define a few standard+-- operations.+++-- | Addition+type family Plus (a :: Peano) (b :: Peano) :: Peano where+ Plus Z b = b+ Plus (S a) b = S (Plus a b)++-- | Subtraction+type family Minus (a :: Peano) (b :: Peano) :: Peano where+ Minus Z b = Z+ Minus (S a) (S b) = Minus a b+ Minus a Z = a++-- | Multiplication+type family Mul (a :: Peano) (b :: Peano) :: Peano where+ Mul Z b = Z+ Mul (S a) b = Plus a (Mul a b)++-- | Less-than-or-equal+type family Le (a :: Peano) (b :: Peano) :: Bool where+ Le Z b = 'True+ Le a Z = 'False+ Le (S a) (S b) = Le a b++-- | Less-than+type family Lt (a :: Peano) (b :: Peano) :: Bool where+ Lt a b = Le (S a) b++-- | Greater-than+type family Gt (a :: Peano) (b :: Peano) :: Bool where+ Gt a b = Le b a++-- | Greater-than-or-equal+type family Ge (a :: Peano) (b :: Peano) :: Bool where+ Ge a b = Lt b a++-- | Maximum+type family Max (a :: Peano) (b :: Peano) :: Peano where+ Max Z b = b+ Max a Z = a+ Max (S a) (S b) = S (Max a b)++-- | Minimum+type family Min (a :: Peano) (b :: Peano) :: Peano where+ Min Z b = Z+ Min a Z = Z+ Min (S a) (S b) = S (Min a b)++-- | Apply a constructor 'f' n-times to an argument 's'+type family Repeat (m :: Peano) (f :: k -> k) (s :: k) :: k where+ Repeat Z f s = s+ Repeat (S m) f s = f (Repeat m f s)++-- | Calculate the size of a context+type family CtxSizeP (ctx :: Ctx k) :: Peano where+ CtxSizeP 'EmptyCtx = Z+ CtxSizeP (xs '::> x) = S (CtxSizeP xs)++------------------------------------------------------------------------+-- * Run time representation of Peano numbers++#ifdef UNSAFE_OPS+-- | The run time value, stored as an Word64+-- As these are unary numbers, we don't worry about overflow.+newtype PeanoRepr (n :: Peano) =+ PeanoRepr { peanoValue :: Word64 }+-- n is Phantom in the definition, but we don't want to allow coerce+type role PeanoRepr nominal+#else+-- | Runtime value+type PeanoRepr = PeanoView+-- | Conversion+peanoValue :: PeanoRepr n -> Word64+peanoValue ZRepr = 0+peanoValue (SRepr m) = 1 + peanoValue m+#endif+ +-- | When we have optimized the runtime representation,+-- we need to have a "view" that decomposes the representation+-- into the standard form.+data PeanoView (n :: Peano) where+ ZRepr :: PeanoView Z+ SRepr :: PeanoRepr n -> PeanoView (S n)++-- | Test whether a number is Zero or Successor+peanoView :: PeanoRepr n -> PeanoView n+#ifdef UNSAFE_OPS+peanoView (PeanoRepr i) =+ if i == 0+ then unsafeCoerce ZRepr+ else unsafeCoerce (SRepr (PeanoRepr (i-1)))+#else+peanoView = id+#endif++-- | convert the view back to the runtime representation+viewRepr :: PeanoView n -> PeanoRepr n+#ifdef UNSAFE_OPS+viewRepr ZRepr = PeanoRepr 0+viewRepr (SRepr n) = PeanoRepr (peanoValue n + 1)+#else+viewRepr = id+#endif++----------------------------------------------------------+-- * Class instances++instance Hashable (PeanoRepr n) where+ hashWithSalt i x = hashWithSalt i (peanoValue x)++instance Eq (PeanoRepr m) where+ _ == _ = True++instance TestEquality PeanoRepr where+#ifdef UNSAFE_OPS+ testEquality (PeanoRepr m) (PeanoRepr n)+ | m == n = Just (unsafeCoerce Refl)+ | otherwise = Nothing+#else + testEquality ZRepr ZRepr = Just Refl+ testEquality (SRepr m1) (SRepr m2)+ | Just Refl <- testEquality m1 m2+ = Just Refl+ testEquality _ _ = Nothing+ +#endif++instance DecidableEq PeanoRepr where+#ifdef UNSAFE_OPS+ decEq (PeanoRepr m) (PeanoRepr n)+ | m == n = Left $ unsafeCoerce Refl+ | otherwise = Right $+ \x -> seq x $ error "Impossible [DecidableEq on PeanoRepr]"+#else+ decEq ZRepr ZRepr = Left Refl+ decEq (SRepr m1) (SRepr m2) =+ case decEq m1 m2 of+ Left Refl -> Left Refl+ Right f -> Right $ \case Refl -> f Refl+ decEq ZRepr (SRepr _) =+ Right $ \case {}+ decEq (SRepr _) ZRepr =+ Right $ \case {}+#endif++instance OrdF PeanoRepr where+#ifdef UNSAFE_OPS+ compareF (PeanoRepr m) (PeanoRepr n)+ | m < n = unsafeCoerce LTF+ | m == n = unsafeCoerce EQF+ | otherwise = unsafeCoerce GTF+#else+ compareF ZRepr ZRepr = EQF+ compareF ZRepr (SRepr _) = LTF+ compareF (SRepr _) ZRepr = GTF+ compareF (SRepr m1) (SRepr m2) =+ case compareF m1 m2 of+ EQF -> EQF+ LTF -> LTF+ GTF -> GTF+#endif++instance PolyEq (PeanoRepr m) (PeanoRepr n) where+ polyEqF x y = (\Refl -> Refl) <$> testEquality x y++-- Display as digits, not in unary+instance Show (PeanoRepr p) where+ show p = show (peanoValue p)++instance ShowF PeanoRepr++instance HashableF PeanoRepr where+ hashWithSaltF = hashWithSalt++----------------------------------------------------------+-- * Implicit runtime Peano numbers++-- | Implicit runtime representation+type KnownPeano = KnownRepr PeanoRepr++instance KnownRepr PeanoRepr Z where+ knownRepr = viewRepr ZRepr+instance (KnownRepr PeanoRepr n) => KnownRepr PeanoRepr (S n) where+ knownRepr = viewRepr (SRepr knownRepr)++----------------------------------------------------------+-- * Operations on runtime numbers+++-- | Zero+zeroP :: PeanoRepr Z+#ifdef UNSAFE_OPS+zeroP = PeanoRepr 0+#else+zeroP = ZRepr+#endif++-- | Successor, Increment+succP :: PeanoRepr n -> PeanoRepr (S n)+#ifdef UNSAFE_OPS+succP (PeanoRepr i) = PeanoRepr (i+1)+#else+succP = SRepr+#endif++-- | Get the predecessor (decrement)+predP :: PeanoRepr (S n) -> PeanoRepr n+#ifdef UNSAFE_OPS+predP (PeanoRepr i) = PeanoRepr (i-1)+#else+predP (SRepr i) = i+#endif++-- | Addition+plusP :: PeanoRepr a -> PeanoRepr b -> PeanoRepr (Plus a b)+#ifdef UNSAFE_OPS+plusP (PeanoRepr a) (PeanoRepr b) = PeanoRepr (a + b)+#else+plusP (SRepr a) b = SRepr (plusP a b)+#endif++-- | Subtraction+minusP :: PeanoRepr a -> PeanoRepr b -> PeanoRepr (Minus a b)+#ifdef UNSAFE_OPS+minusP (PeanoRepr a) (PeanoRepr b) = PeanoRepr (a - b)+#else+minusP ZRepr _b = ZRepr+minusP (SRepr a) (SRepr b) = minusP a b+minusP a ZRepr = a+#endif++-- | Multiplication+mulP :: PeanoRepr a -> PeanoRepr b -> PeanoRepr (Mul a b)+#ifdef UNSAFE_OPS+mulP (PeanoRepr a) (PeanoRepr b) = PeanoRepr (a * b)+#else+mulP ZRepr _b = ZRepr+mulP (SRepr a) b = plusP a (mulP a b)+#endif++-- | Maximum+maxP :: PeanoRepr a -> PeanoRepr b -> PeanoRepr (Max a b)+#ifdef UNSAFE_OPS+maxP (PeanoRepr a) (PeanoRepr b) = PeanoRepr (max a b)+#else+maxP ZRepr b = b+maxP a ZRepr = a+maxP (SRepr a) (SRepr b) = SRepr (maxP a b)+#endif++-- | Minimum+minP :: PeanoRepr a -> PeanoRepr b -> PeanoRepr (Min a b)+#ifdef UNSAFE_OPS+minP (PeanoRepr a) (PeanoRepr b) = PeanoRepr (min a b)+#else+minP ZRepr _b = ZRepr+minP _a ZRepr = ZRepr+minP (SRepr a) (SRepr b) = SRepr (minP a b)+#endif++-- | Less-than-or-equal-to+leP :: PeanoRepr a -> PeanoRepr b -> BoolRepr (Le a b)+#ifdef UNSAFE_OPS+leP (PeanoRepr a) (PeanoRepr b) =+ if a <= b then unsafeCoerce (TrueRepr)+ else unsafeCoerce(FalseRepr)+#else+leP ZRepr ZRepr = TrueRepr+leP ZRepr (SRepr _) = TrueRepr+leP (SRepr _) ZRepr = FalseRepr+leP (SRepr a) (SRepr b) = leP a b+#endif++-- | Less-than+ltP :: PeanoRepr a -> PeanoRepr b -> BoolRepr (Lt a b)+ltP a b = leP (succP a) b++-- | Greater-than-or-equal-to+geP :: PeanoRepr a -> PeanoRepr b -> BoolRepr (Ge a b)+geP a b = ltP b a++-- | Greater-than+gtP :: PeanoRepr a -> PeanoRepr b -> BoolRepr (Gt a b)+gtP a b = leP b a+++-- | Apply a constructor 'f' n-times to an argument 's'+repeatP :: PeanoRepr m -> (forall a. repr a -> repr (f a)) -> repr s -> repr (Repeat m f s)+repeatP n f s = case peanoView n of+ ZRepr -> s+ SRepr m -> f (repeatP m f s)++-- | Calculate the size of a context+ctxSizeP :: Assignment f ctx -> PeanoRepr (CtxSizeP ctx)+ctxSizeP r = case viewAssign r of+ AssignEmpty -> zeroP+ AssignExtend a _ -> succP (ctxSizeP a)++------------------------------------------------------------------------+-- * Some PeanoRepr++-- | Convert a 'Word64' to a 'PeanoRepr'+mkPeanoRepr :: Word64 -> Some PeanoRepr+#ifdef UNSAFE_OPS+mkPeanoRepr n = Some (PeanoRepr n)+#else+mkPeanoRepr 0 = Some ZRepr+mkPeanoRepr n = case mkPeanoRepr (n - 1) of+ Some mr -> Some (SRepr mr)+#endif ++-- | Turn an @Integral@ value into a 'PeanoRepr'. Returns @Nothing@+-- if the given value is negative.+somePeano :: Integral a => a -> Maybe (Some PeanoRepr)+somePeano x | x >= 0 = Just . mkPeanoRepr $! fromIntegral x+somePeano _ = Nothing++-- | Return the maximum of two representations.+maxPeano :: PeanoRepr m -> PeanoRepr n -> Some PeanoRepr+maxPeano x y = Some (maxP x y)++-- | Return the minimum of two representations.+minPeano :: PeanoRepr m -> PeanoRepr n -> Some PeanoRepr+minPeano x y = Some (minP x y)++-- | List length as a Peano number+peanoLength :: [a] -> Some PeanoRepr+peanoLength [] = Some zeroP+peanoLength (_:xs) = case peanoLength xs of+ Some n -> Some (succP n)+++------------------------------------------------------------------------+-- * Properties about Peano numbers+--+-- The safe version of these properties includes a runtime proof of+-- the equality. The unsafe version has no run-time+-- computation. Therefore, in the unsafe version, the "Repr" arguments+-- can be used as proxies (i.e. called using 'undefined') but must be+-- supplied to the safe versions.+++-- | Context size commutes with context append+plusCtxSizeAxiom :: forall t1 t2 f.+ Assignment f t1 -> Assignment f t2 ->+ CtxSizeP (t1 <+> t2) :~: Plus (CtxSizeP t2) (CtxSizeP t1)+#ifdef UNSAFE_OPS+plusCtxSizeAxiom _t1 _t2 = unsafeCoerce Refl+#else+plusCtxSizeAxiom t1 t2 =+ case viewAssign t2 of+ AssignEmpty -> Refl+ AssignExtend t2' _+ | Refl <- plusCtxSizeAxiom t1 t2' -> Refl+#endif++-- | Minus distributes over plus+--+minusPlusAxiom :: forall n t t'.+ PeanoRepr n -> PeanoRepr t -> PeanoRepr t' -> + Minus n (Plus t' t) :~: Minus (Minus n t') t+#ifdef UNSAFE_OPS+minusPlusAxiom _n _t _t' = unsafeCoerce Refl+#else+minusPlusAxiom n t t' = case peanoView t' of+ ZRepr -> Refl+ SRepr t1' -> case peanoView n of+ ZRepr -> Refl+ SRepr n1 -> case minusPlusAxiom n1 t t1' of+ Refl -> Refl+#endif++-- | We can reshuffle minus with less than+--+ltMinusPlusAxiom :: forall n t t'.+ (Lt t (Minus n t') ~ 'True) =>+ PeanoRepr n -> PeanoRepr t -> PeanoRepr t' ->+ Lt (Plus t' t) n :~: 'True+#ifdef UNSAFE_OPS+ltMinusPlusAxiom _n _t _t' = unsafeCoerce Refl+#else+ltMinusPlusAxiom n t t' = case peanoView n of+ SRepr m -> case peanoView t' of+ ZRepr -> Refl+ SRepr t1' -> case ltMinusPlusAxiom m t t1' of+ Refl -> Refl+#endif++------------------------------------------------------------------------+-- LocalWords: PeanoRepr runtime Peano unary
src/Data/Parameterized/Some.hs view
@@ -1,8 +1,9 @@ ------------------------------------------------------------------------ -- | -- Module : Data.Parameterized.Some--- Copyright : (c) Galois, Inc 2014+-- Copyright : (c) Galois, Inc 2014-2019 -- Maintainer : Joe Hendrix <jhendrix@galois.com>+-- Description : a GADT that hides a type parameter -- -- This module provides 'Some', a GADT that hides a type parameter. ------------------------------------------------------------------------
src/Data/Parameterized/SymbolRepr.hs view
@@ -1,6 +1,7 @@ {-|-Copyright : (c) Galois, Inc 2014-2015+Copyright : (c) Galois, Inc 2014-2019 Maintainer : Joe Hendrix <jhendrix@galois.com>+Description : a type family for representing a type-level string (AKA symbol) at runtime This defines a type family 'SymbolRepr' for representing a type-level string (AKA symbol) at runtime. This can be used to branch on a type-level value.@@ -16,13 +17,11 @@ {-# LANGUAGE ExplicitNamespaces #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GADTs #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE RankNTypes #-}-{-# LANGUAGE PatternGuards #-} {-# LANGUAGE Trustworthy #-} module Data.Parameterized.SymbolRepr ( -- * SymbolRepr
src/Data/Parameterized/TH/GADT.hs view
@@ -1,8 +1,9 @@ ------------------------------------------------------------------------ -- | -- Module : Data.Parameterized.TH.GADT--- Copyright : (c) Galois, Inc 2013-2014+-- Copyright : (c) Galois, Inc 2013-2019 -- Maintainer : Joe Hendrix <jhendrix@galois.com>+-- Description : Template Haskell primitives for working with large GADTs -- -- This module declares template Haskell primitives so that it is easier -- to work with GADTs that have many constructors.@@ -79,7 +80,7 @@ data TypePat = TypeApp TypePat TypePat -- ^ The application of a type. | AnyType -- ^ Match any type.- | DataArg Int -- ^ Match the ith argument of the data type we are traversing.+ | DataArg Int -- ^ Match the i'th argument of the data type we are traversing. | ConType TypeQ -- ^ Match a ground type. matchTypePat :: [Type] -> TypePat -> Type -> Q Bool@@ -198,7 +199,9 @@ in mkSimpleEqF dVars bnd pats con -- | @structuralTypeEquality f@ returns a function with the type:--- forall x y . f x -> f y -> Maybe (x :~: y)+-- @+-- forall x y . f x -> f y -> Maybe (x :~: y)+-- @ structuralTypeEquality :: TypeQ -> [(TypePat,ExpQ)] -> ExpQ structuralTypeEquality tpq pats = do d <- reifyDatatype =<< asTypeCon "structuralTypeEquality" =<< tpq@@ -214,7 +217,9 @@ else [| \x y -> $(caseE [| x |] (trueEqs [| y |])) |] -- | @structuralTypeOrd f@ returns a function with the type:--- forall x y . f x -> f y -> OrderingF x y+-- @+-- forall x y . f x -> f y -> OrderingF x y+-- @ -- -- This implementation avoids matching on both the first and second -- parameters in a simple case expression in order to avoid stressing@@ -256,12 +261,12 @@ | (i,con) <- zip [0..] (datatypeCons d) ] -- | Generate a list of fresh names using the base name--- numbered 1 to n to make them useful in conjunction with--- @-dsuppress-unqiues@.+-- and numbered 1 to @n@ to make them useful in conjunction with+-- @-dsuppress-uniques@. newNames :: String {- ^ base name -} -> Int {- ^ quantity -} ->- Q [Name] {- ^ list of names: base1, base2.. -}+ Q [Name] {- ^ list of names: @base1@, @base2@, ... -} newNames base n = traverse (\i -> newName (base ++ show i)) [1..n] @@ -273,7 +278,7 @@ EQF -> $(r) |] --- | Compare two variables and use following comparison if they are different.+-- | Compare two variables, returning the third argument if they are equal. -- -- This returns an 'OrdF' instance. joinCompareToOrdF :: Name -> Name -> ExpQ -> ExpQ@@ -284,7 +289,7 @@ EQ -> $(r) |] - -- Match expression with given type to variables+-- | Match expression with given type to variables matchOrdArguments :: [Type] -- ^ Types bound by data arguments -> [(TypePat,ExpQ)] -- ^ Patterns for matching arguments@@ -343,7 +348,7 @@ -> Q [MatchQ] mkOrdF d pats = mkSimpleOrdF (datatypeVars d) pats --- | Find the first recurseArg f var tp@ applies @f@ to @var@ where @var@ has type @tp@.+-- | @recurseArg f var tp@ applies @f@ to @var@ where @var@ has type @tp@. recurseArg :: (Type -> Q (Maybe ExpQ)) -> ExpQ -- ^ Function to apply -> ExpQ@@ -361,7 +366,7 @@ -- | @traverseAppMatch f c@ builds a case statement that matches a term with -- the constructor @c@ and applies @f@ to each argument.-traverseAppMatch :: (Type -> Q (Maybe ExpQ)) -- Pattern match function+traverseAppMatch :: (Type -> Q (Maybe ExpQ)) -- ^ Pattern match function -> ExpQ -- ^ Function to apply to each argument recursively. -> ConstructorInfo -- ^ Constructor to match. -> MatchQ -- ^ Match expression that
src/Data/Parameterized/TraversableF.hs view
@@ -1,14 +1,17 @@ ------------------------------------------------------------------------ -- | -- Module : Data.Parameterized.TraversableF--- Copyright : (c) Galois, Inc 2014-2015+-- Copyright : (c) Galois, Inc 2014-2019 -- Maintainer : Joe Hendrix <jhendrix@galois.com>+-- Description : Traversing structures having a single parametric type -- -- This module declares classes for working with structures that accept -- a single parametric type parameter. ------------------------------------------------------------------------+{-# LANGUAGE InstanceSigs #-} {-# LANGUAGE PolyKinds #-} {-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE Trustworthy #-} module Data.Parameterized.TraversableF ( FunctorF(..)@@ -24,9 +27,12 @@ import Control.Applicative import Control.Monad.Identity import Data.Coerce+import Data.Functor.Compose (Compose(..)) import Data.Monoid import GHC.Exts (build) +import Data.Parameterized.TraversableFC+ -- | A parameterized type that is a functor on all instances. class FunctorF m where fmapF :: (forall x . f x -> g x) -> m f -> m g@@ -42,7 +48,7 @@ (#.) :: Coercible b c => (b -> c) -> (a -> b) -> (a -> c) (#.) _f = coerce --- | This is a generalization of the @Foldable@ class to+-- | This is a generalization of the 'Foldable' class to -- structures over parameterized terms. class FoldableF (t :: (k -> *) -> *) where {-# MINIMAL foldMapF | foldrF #-}@@ -76,11 +82,11 @@ toListF :: (forall tp . f tp -> a) -> t f -> [a] toListF f t = build (\c n -> foldrF (\e v -> c (f e) v) n t) --- | Return 'True' if all values satisfy predicate.+-- | Return 'True' if all values satisfy the predicate. allF :: FoldableF t => (forall tp . f tp -> Bool) -> t f -> Bool allF p = getAll #. foldMapF (All #. p) --- | Return 'True' if any values satisfy predicate.+-- | Return 'True' if any values satisfy the predicate. anyF :: FoldableF t => (forall tp . f tp -> Bool) -> t f -> Bool anyF p = getAny #. foldMapF (Any #. p) @@ -112,5 +118,30 @@ -- | Map each element of a structure to an action, evaluate -- these actions from left to right, and ignore the results.-traverseF_ :: (FoldableF t, Applicative f) => (forall s . e s -> f ()) -> t e -> f ()+traverseF_ :: (FoldableF t, Applicative f) => (forall s . e s -> f a) -> t e -> f () traverseF_ f = foldrF (\e r -> f e *> r) (pure ())++------------------------------------------------------------------------+-- TraversableF (Compose s t)++instance ( FunctorF (s :: (k -> *) -> *)+ , FunctorFC (t :: (l -> *) -> (k -> *))+ ) =>+ FunctorF (Compose s t) where+ fmapF f (Compose v) = Compose $ fmapF (fmapFC f) v++instance ( TraversableF (s :: (k -> *) -> *)+ , TraversableFC (t :: (l -> *) -> (k -> *))+ ) =>+ FoldableF (Compose s t) where+ foldMapF = foldMapFDefault++-- | Traverse twice over: go under the @t@, under the @s@ and lift @m@ out.+instance ( TraversableF (s :: (k -> *) -> *)+ , TraversableFC (t :: (l -> *) -> (k -> *))+ ) =>+ TraversableF (Compose s t) where+ traverseF :: forall (f :: l -> *) (g :: l -> *) m. (Applicative m) =>+ (forall (u :: l). f u -> m (g u))+ -> Compose s t f -> m (Compose s t g)+ traverseF f (Compose v) = Compose <$> traverseF (traverseFC f) v
src/Data/Parameterized/TraversableFC.hs view
@@ -3,6 +3,7 @@ -- Module : Data.Parameterized.TraversableFC -- Copyright : (c) Galois, Inc 2014-2015 -- Maintainer : Joe Hendrix <jhendrix@galois.com>+-- Description : Traversing structures having a single parametric type followed by a fixed kind. -- -- This module declares classes for working with structures that accept -- a parametric type parameter followed by some fixed kind.@@ -77,12 +78,12 @@ ------------------------------------------------------------------------ -- FoldableF --- | This is a coercision used to avoid overhead associated+-- | This is a coercion used to avoid overhead associated -- with function composition. (#.) :: Coercible b c => (b -> c) -> (a -> b) -> (a -> c) (#.) _f = coerce --- | This is a generalization of the @Foldable@ class to+-- | This is a generalization of the 'Foldable' class to -- structures over parameterized terms. class FoldableFC (t :: (k -> *) -> l -> *) where {-# MINIMAL foldMapFC | foldrFC #-}@@ -150,12 +151,12 @@ -- | Map each element of a structure to an action, evaluate -- these actions from left to right, and ignore the results.-traverseFC_ :: (FoldableFC t, Applicative m) => (forall x. f x -> m ()) -> (forall x. t f x -> m ())+traverseFC_ :: (FoldableFC t, Applicative m) => (forall x. f x -> m a) -> (forall x. t f x -> m ()) traverseFC_ f = foldrFC (\e r -> f e *> r) (pure ()) {-# INLINE traverseFC_ #-} -- | Map each element of a structure to an action, evaluate -- these actions from left to right, and ignore the results.-forMFC_ :: (FoldableFC t, Applicative m) => t f c -> (forall x. f x -> m ()) -> m ()+forMFC_ :: (FoldableFC t, Applicative m) => t f c -> (forall x. f x -> m a) -> m () forMFC_ v f = traverseFC_ f v {-# INLINE forMFC_ #-}
src/Data/Parameterized/Utils/BinTree.hs view
@@ -1,6 +1,6 @@ {-| Description : Utilities for balanced binary trees.-Copyright : (c) Galois, Inc 2014+Copyright : (c) Galois, Inc 2014-2019 Maintainer : Joe Hendrix <jhendrix@galois.com> -} {-# LANGUAGE ConstraintKinds #-}@@ -64,7 +64,7 @@ ------------------------------------------------------------------------ -- Updated --- | Updated a contains a value that has been flagged on whether it was+-- | @Updated a@ contains a value that has been flagged on whether it was -- modified by an operation. data Updated a = Updated !a@@ -92,7 +92,7 @@ delta = 3 ratio = 2 --- `balanceL p l r` returns a balanced tree for the sequence @l ++ [p] ++ r@.+-- | @balanceL p l r@ returns a balanced tree for the sequence @l ++ [p] ++ r@. -- -- It assumes that @l@ and @r@ are close to being balanced, and that only -- @l@ may contain too many elements.@@ -108,7 +108,7 @@ _ -> bin p l r {-# INLINE balanceL #-} --- `balanceR p l r` returns a balanced tree for the sequence @l ++ [p] ++ r@.+-- | @balanceR p l r@ returns a balanced tree for the sequence @l ++ [p] ++ r@. -- -- It assumes that @l@ and @r@ are close to being balanced, and that only -- @r@ may contain too many elements.@@ -137,7 +137,7 @@ TipTree -> bin p tip tip BinTree q l r -> balanceL q (insertMin p l) r --- | link is called to insert a key and value between two disjoint subtrees.+-- | @link@ is called to insert a key and value between two disjoint subtrees. link :: IsBinTree c e => e -> c -> c -> c link p l r = case (asBin l, asBin r) of@@ -210,7 +210,7 @@ EQ -> Unchanged (bin x l r) {-# INLINABLE insert #-} --- | 'glue l r' concatenates @l@ and @r@.+-- | @glue l r@ concatenates @l@ and @r@. -- -- It assumes that @l@ and @r@ are already balanced with respect to each other. glue :: IsBinTree c e => c -> c -> c@@ -247,7 +247,7 @@ -- filter -- | Returns only entries that are less than predicate with respect to the ordering--- and Nothing if no elements are discared.+-- and Nothing if no elements are discarded. filterGt :: IsBinTree c e => (e -> Ordering) -> c -> MaybeS c filterGt k t = case asBin t of@@ -260,7 +260,7 @@ {-# INLINABLE filterGt #-} --- | @filterLt' k m@ returns submap of @m@ that only contains entries+-- | @filterLt k m@ returns submap of @m@ that only contains entries -- that are smaller than @k@. If no entries are deleted then return Nothing. filterLt :: IsBinTree c e => (e -> Ordering) -> c -> MaybeS c filterLt k t =@@ -276,8 +276,8 @@ ------------------------------------------------------------------------ -- Union --- Insert a new key and value in the map if it is not already present.--- Used by `union`.+-- | Insert a new key and value in the map if it is not already present.+-- Used by 'union'. insertR :: forall c e . (IsBinTree c e) => (e -> e -> Ordering) -> e -> c -> c insertR comp e m = fromMaybeS m (go e m) where
+ src/Data/Parameterized/Utils/Endian.hs view
@@ -0,0 +1,16 @@+{-|+Description: A common location for defining multi-byte value ordering.+Copyright : (c) Galois, Inc 2019+-}++module Data.Parameterized.Utils.Endian where++-- | Determines the composition of smaller numeric values into larger values.+--+-- BigEndian = most significant values in the lowest index location / first+-- LittleEndian = least significant values in the lowest index location / first+--+-- Value: 0x01020304+-- BigEndian = [ 0x01, 0x02, 0x03, 0x04 ]+-- LittleEndian = [ 0x04, 0x03, 0x02, 0x01 ]+data Endian = LittleEndian | BigEndian deriving (Eq,Show,Ord)
+ src/Data/Parameterized/Vector.hs view
@@ -0,0 +1,560 @@+{-# Language GADTs, DataKinds, TypeOperators, BangPatterns #-}+{-# Language PatternGuards #-}+{-# Language TypeApplications, ScopedTypeVariables #-}+{-# Language Rank2Types, RoleAnnotations #-}+{-# Language CPP #-}+#if __GLASGOW_HASKELL__ >= 805+{-# Language NoStarIsType #-}+#endif+{-|+Copyright : (c) Galois, Inc 2014-2019++A fixed-size vector of typed elements.++NB: This module contains an orphan instance. It will be included in GHC 8.10,+see https://gitlab.haskell.org/ghc/ghc/merge_requests/273.+-}+module Data.Parameterized.Vector+ ( Vector+ -- * Lists+ , fromList+ , toList++ -- * Length+ , length+ , nonEmpty+ , lengthInt++ -- * Indexing+ , elemAt+ , elemAtMaybe+ , elemAtUnsafe++ -- * Update+ , insertAt+ , insertAtMaybe++ -- * Sub sequences+ , uncons+ , slice+ , Data.Parameterized.Vector.take++ -- * Zipping+ , zipWith+ , zipWithM+ , zipWithM_+ , interleave++ -- * Reorder+ , shuffle+ , reverse+ , rotateL+ , rotateR+ , shiftL+ , shiftR++ -- * Construction+ , singleton+ , cons+ , snoc+ , generate+ , generateM++ -- * Splitting and joining+ -- ** General+ , joinWithM+ , joinWith+ , splitWith+ , splitWithA++ -- ** Vectors+ , split+ , join+ , append++ ) where++import qualified Data.Vector as Vector+import Data.Functor.Compose+import Data.Coerce+import Data.Vector.Mutable (MVector)+import qualified Data.Vector.Mutable as MVector+import Control.Monad.ST+import Data.Functor.Identity+import Data.Parameterized.NatRepr+import Data.Parameterized.NatRepr.Internal+import Data.Proxy+import Prelude hiding (length,reverse,zipWith)+import Numeric.Natural++import Data.Parameterized.Utils.Endian++-- | Fixed-size non-empty vectors.+data Vector n a where+ Vector :: (1 <= n) => !(Vector.Vector a) -> Vector n a++type role Vector nominal representational++instance Eq a => Eq (Vector n a) where+ (Vector x) == (Vector y) = x == y++instance Show a => Show (Vector n a) where+ show (Vector x) = show x++-- | Get the elements of the vector as a list, lowest index first.+toList :: Vector n a -> [a]+toList (Vector v) = Vector.toList v+{-# Inline toList #-}++-- NOTE: We are using the raw 'NatRepr' constructor here, which is unsafe.+-- | Length of the vector.+-- @O(1)@+length :: Vector n a -> NatRepr n+length (Vector xs) = NatRepr (fromIntegral (Vector.length xs) :: Natural)+{-# INLINE length #-}++-- | The length of the vector as an "Int".+lengthInt :: Vector n a -> Int+lengthInt (Vector xs) = Vector.length xs+{-# Inline lengthInt #-}++elemAt :: ((i+1) <= n) => NatRepr i -> Vector n a -> a+elemAt n (Vector xs) = xs Vector.! widthVal n++-- | Get the element at the given index.+-- @O(1)@+elemAtMaybe :: Int -> Vector n a -> Maybe a+elemAtMaybe n (Vector xs) = xs Vector.!? n+{-# INLINE elemAt #-}++-- | Get the element at the given index.+-- Raises an exception if the element is not in the vector's domain.+-- @O(1)@+elemAtUnsafe :: Int -> Vector n a -> a+elemAtUnsafe n (Vector xs) = xs Vector.! n+{-# INLINE elemAtUnsafe #-}+++-- | Insert an element at the given index.+-- @O(n)@.+insertAt :: ((i + 1) <= n) => NatRepr i -> a -> Vector n a -> Vector n a+insertAt n a (Vector xs) = Vector (Vector.unsafeUpd xs [(widthVal n,a)])++-- | Insert an element at the given index.+-- Return 'Nothing' if the element is outside the vector bounds.+-- @O(n)@.+insertAtMaybe :: Int -> a -> Vector n a -> Maybe (Vector n a)+insertAtMaybe n a (Vector xs)+ | 0 <= n && n < Vector.length xs = Just (Vector (Vector.unsafeUpd xs [(n,a)]))+ | otherwise = Nothing+++-- | Proof that the length of this vector is not 0.+nonEmpty :: Vector n a -> LeqProof 1 n+nonEmpty (Vector _) = LeqProof+{-# Inline nonEmpty #-}+++-- | Remove the first element of the vector, and return the rest, if any.+uncons :: forall n a. Vector n a -> (a, Either (n :~: 1) (Vector (n-1) a))+uncons v@(Vector xs) = (Vector.head xs, mbTail)+ where+ mbTail :: Either (n :~: 1) (Vector (n - 1) a)+ mbTail = case testStrictLeq (knownNat @1) (length v) of+ Left n2_leq_n ->+ do LeqProof <- return (leqSub2 n2_leq_n (leqRefl (knownNat @1)))+ return (Vector (Vector.tail xs))+ Right Refl -> Left Refl+{-# Inline uncons #-}+++--------------------------------------------------------------------------------++-- | Make a vector of the given length and element type.+-- Returns "Nothing" if the input list does not have the right number of+-- elements.+-- @O(n)@.+fromList :: (1 <= n) => NatRepr n -> [a] -> Maybe (Vector n a)+fromList n xs+ | widthVal n == Vector.length v = Just (Vector v)+ | otherwise = Nothing+ where+ v = Vector.fromList xs+{-# INLINE fromList #-}+++-- | Extract a subvector of the given vector.+slice :: (i + w <= n, 1 <= w) =>+ NatRepr i {- ^ Start index -} ->+ NatRepr w {- ^ Width of sub-vector -} ->+ Vector n a -> Vector w a+slice i w (Vector xs) = Vector (Vector.slice (widthVal i) (widthVal w) xs)+{-# INLINE slice #-}++-- | Take the front (lower-indexes) part of the vector.+take :: forall n x a. (1 <= n) => NatRepr n -> Vector (n + x) a -> Vector n a+take | LeqProof <- prf = slice (knownNat @0)+ where+ prf = leqAdd (leqRefl (Proxy @n)) (Proxy @x)++--------------------------------------------------------------------------------++instance Functor (Vector n) where+ fmap f (Vector xs) = Vector (Vector.map f xs)+ {-# Inline fmap #-}++instance Foldable (Vector n) where+ foldMap f (Vector xs) = foldMap f xs++instance Traversable (Vector n) where+ traverse f (Vector xs) = Vector <$> traverse f xs+ {-# Inline traverse #-}++-- | Zip two vectors, potentially changing types.+-- @O(n)@+zipWith :: (a -> b -> c) -> Vector n a -> Vector n b -> Vector n c+zipWith f (Vector xs) (Vector ys) = Vector (Vector.zipWith f xs ys)+{-# Inline zipWith #-}++zipWithM :: Monad m => (a -> b -> m c) ->+ Vector n a -> Vector n b -> m (Vector n c)+zipWithM f (Vector xs) (Vector ys) = Vector <$> Vector.zipWithM f xs ys+{-# Inline zipWithM #-}++zipWithM_ :: Monad m => (a -> b -> m ()) -> Vector n a -> Vector n b -> m ()+zipWithM_ f (Vector xs) (Vector ys) = Vector.zipWithM_ f xs ys+{-# Inline zipWithM_ #-}++{- | Interleave two vectors. The elements of the first vector are+at even indexes in the result, the elements of the second are at odd indexes. -}+interleave ::+ forall n a. (1 <= n) => Vector n a -> Vector n a -> Vector (2 * n) a+interleave (Vector xs) (Vector ys)+ | LeqProof <- leqMulPos (Proxy @2) (Proxy @n) = Vector zs+ where+ len = Vector.length xs + Vector.length ys+ zs = Vector.generate len (\i -> let v = if even i then xs else ys+ in v Vector.! (i `div` 2))+++--------------------------------------------------------------------------------++{- | Move the elements around, as specified by the given function.+ * Note: the reindexing function says where each of the elements+ in the new vector come from.+ * Note: it is OK for the same input element to end up in mulitple places+ in the result.+@O(n)@+-}+shuffle :: (Int -> Int) -> Vector n a -> Vector n a+shuffle f (Vector xs) = Vector ys+ where+ ys = Vector.generate (Vector.length xs) (\i -> xs Vector.! f i)+{-# Inline shuffle #-}++-- | Reverse the vector.+reverse :: forall a n. (1 <= n) => Vector n a -> Vector n a+reverse x = shuffle (\i -> lengthInt x - i - 1) x++-- | Rotate "left". The first element of the vector is on the "left", so+-- rotate left moves all elemnts toward the corresponding smaller index.+-- Elements that fall off the beginning end up at the end.+rotateL :: Int -> Vector n a -> Vector n a+rotateL !n xs = shuffle rotL xs+ where+ !len = lengthInt xs+ rotL i = (i + n) `mod` len -- `len` is known to be >= 1+{-# Inline rotateL #-}++-- | Rotate "right". The first element of the vector is on the "left", so+-- rotate right moves all elemnts toward the corresponding larger index.+-- Elements that fall off the end, end up at the beginning.+rotateR :: Int -> Vector n a -> Vector n a+rotateR !n xs = shuffle rotR xs+ where+ !len = lengthInt xs+ rotR i = (i - n) `mod` len -- `len` is known to be >= 1+{-# Inline rotateR #-}++{- | Move all elements towards smaller indexes.+Elements that fall off the front are ignored.+Empty slots are filled in with the given element.+@O(n)@. -}+shiftL :: Int -> a -> Vector n a -> Vector n a+shiftL !x a (Vector xs) = Vector ys+ where+ !len = Vector.length xs+ ys = Vector.generate len (\i -> let j = i + x+ in if j >= len then a else xs Vector.! j)+{-# Inline shiftL #-}++{- | Move all elements towards the larger indexes.+Elements that "fall" off the end are ignored.+Empty slots are filled in with the given element.+@O(n)@. -}+shiftR :: Int -> a -> Vector n a -> Vector n a+shiftR !x a (Vector xs) = Vector ys+ where+ !len = Vector.length xs+ ys = Vector.generate len (\i -> let j = i - x+ in if j < 0 then a else xs Vector.! j)+{-# Inline shiftR #-}++-------------------------------------------------------------------------------i++-- | Append two vectors. The first one is at lower indexes in the result.+append :: Vector m a -> Vector n a -> Vector (m + n) a+append v1@(Vector xs) v2@(Vector ys) =+ case leqAddPos (length v1) (length v2) of { LeqProof ->+ Vector (xs Vector.++ ys)+ }+{-# Inline append #-}++--------------------------------------------------------------------------------+-- Constructing Vectors++-- | Vector with exactly one element+singleton :: forall a. a -> Vector 1 a+singleton a = Vector (Vector.singleton a)++leqLen :: forall n a. Vector n a -> LeqProof 1 (n + 1)+leqLen v =+ let leqSucc :: forall f z. f z -> LeqProof z (z + 1)+ leqSucc fz = leqAdd (leqRefl fz :: LeqProof z z) (knownNat @1)+ in leqTrans (nonEmpty v :: LeqProof 1 n) (leqSucc (length v))++-- | Add an element to the head of a vector+cons :: forall n a. a -> Vector n a -> Vector (n+1) a+cons a v@(Vector x) = case leqLen v of LeqProof -> (Vector (Vector.cons a x))++-- | Add an element to the tail of a vector+snoc :: forall n a. Vector n a -> a -> Vector (n+1) a+snoc v@(Vector x) a = case leqLen v of LeqProof -> (Vector (Vector.snoc x a))++-- | This newtype wraps Vector so that we can curry it in the call to+-- @natRecBounded@. It adds 1 to the length so that the base case is+-- a @Vector@ of non-zero length.+newtype Vector' a n = MkVector' (Vector (n+1) a)++unVector' :: Vector' a n -> Vector (n+1) a+unVector' (MkVector' v) = v++snoc' :: forall a m. Vector' a m -> a -> Vector' a (m+1)+snoc' v = MkVector' . snoc (unVector' v)++generate' :: forall h a+ . NatRepr h+ -> (forall n. (n <= h) => NatRepr n -> a)+ -> Vector' a h+generate' h gen =+ case isZeroOrGT1 h of+ Left Refl -> base+ Right LeqProof ->+ case (minusPlusCancel h (knownNat @1) :: h - 1 + 1 :~: h) of { Refl ->+ natRecBounded (decNat h) (decNat h) base step+ }+ where base :: Vector' a 0+ base = MkVector' $ singleton (gen (knownNat @0))+ step :: forall m. (1 <= h, m <= h - 1)+ => NatRepr m -> Vector' a m -> Vector' a (m + 1)+ step m v =+ case minusPlusCancel h (knownNat @1) :: h - 1 + 1 :~: h of { Refl ->+ case (leqAdd2 (LeqProof :: LeqProof m (h-1))+ (LeqProof :: LeqProof 1 1) :: LeqProof (m+1) h) of { LeqProof ->+ snoc' v (gen (incNat m))+ }}++-- | Apply a function to each element in a range starting at zero;+-- return the a vector of values obtained.+-- cf. both @natFromZero@ and @Data.Vector.generate@+generate :: forall h a+ . NatRepr h+ -> (forall n. (n <= h) => NatRepr n -> a)+ -> Vector (h + 1) a+generate h gen = unVector' (generate' h gen)++-- | Since @Vector@ is traversable, we can pretty trivially sequence+-- @natFromZeroVec@ inside a monad.+generateM :: forall m h a. (Monad m)+ => NatRepr h+ -> (forall n. (n <= h) => NatRepr n -> m a)+ -> m (Vector (h + 1) a)+generateM h gen = sequence $ generate h gen++--------------------------------------------------------------------------------++coerceVec :: Coercible a b => Vector n a -> Vector n b+coerceVec = coerce++-- | Monadically join a vector of values, using the given function.+-- This functionality can sometimes be reproduced by creating a newtype+-- wrapper and using @joinWith@, this implementation is provided for+-- convenience.+joinWithM ::+ forall m f n w.+ (1 <= w, Monad m) =>+ (forall l. (1 <= l) => NatRepr l -> f w -> f l -> m (f (w + l)))+ {- ^ A function for joining contained elements. The first argument is+ the size of the accumulated third term, and the second argument+ is the element to join to the accumulated term. The function+ can use any join strategy desired (prepending/"BigEndian",+ appending/"LittleEndian", etc.). -}+ -> NatRepr w+ -> Vector n (f w)+ -> m (f (n * w))++joinWithM jn w = fmap fst . go+ where+ go :: forall l. Vector l (f w) -> m (f (l * w), NatRepr (l * w))+ go exprs =+ case uncons exprs of+ (a, Left Refl) -> return (a, w)+ (a, Right rest) ->+ case nonEmpty rest of { LeqProof ->+ case leqMulPos (length rest) w of { LeqProof ->+ case nonEmpty exprs of { LeqProof ->+ case lemmaMul w (length exprs) of { Refl -> do+ -- @siddharthist: This could probably be written applicatively?+ (res, sz) <- go rest+ joined <- jn sz a res+ return (joined, addNat w sz)+ }}}}++-- | Join a vector of vectors, using the given function to combine the+-- sub-vectors.+joinWith ::+ forall f n w.+ (1 <= w) =>+ (forall l. (1 <= l) => NatRepr l -> f w -> f l -> f (w + l))+ {- ^ A function for joining contained elements. The first argument is+ the size of the accumulated third term, and the second argument+ is the element to join to the accumulated term. The function+ can use any join strategy desired (prepending/"BigEndian",+ appending/"LittleEndian", etc.). -}+ -> NatRepr w+ -> Vector n (f w)+ -> f (n * w)+joinWith jn w v = runIdentity $ joinWithM (\n x -> pure . (jn n x)) w v+{-# Inline joinWith #-}++-- | Split a vector into a vector of vectors.+--+-- The "Endian" parameter determines the ordering of the inner+-- vectors. If "LittleEndian", then less significant bits go into+-- smaller indexes. If "BigEndian", then less significant bits go+-- into larger indexes. See the documentation for 'split' for more+-- details.+splitWith :: forall f w n.+ (1 <= w, 1 <= n) =>+ Endian ->+ (forall i. (i + w <= n * w) =>+ NatRepr (n * w) -> NatRepr i -> f (n * w) -> f w)+ {- ^ A function for slicing out a chunk of length @w@, starting at @i@ -} ->+ NatRepr n -> NatRepr w -> f (n * w) -> Vector n (f w)+splitWith endian select n w val = Vector (Vector.create initializer)+ where+ len = widthVal n+ start :: Int+ next :: Int -> Int+ (start,next) = case endian of+ LittleEndian -> (0, succ)+ BigEndian -> (len - 1, pred)++ initializer :: forall s. ST s (MVector s (f w))+ initializer =+ do LeqProof <- return (leqMulPos n w)+ LeqProof <- return (leqMulMono n w)++ v <- MVector.new len+ let fill :: Int -> NatRepr i -> ST s ()+ fill loc i =+ let end = addNat i w in+ case testLeq end inLen of+ Just LeqProof ->+ do MVector.write v loc (select inLen i val)+ fill (next loc) end+ Nothing -> return ()+++ fill start (knownNat @0)+ return v++ inLen :: NatRepr (n * w)+ inLen = natMultiply n w+{-# Inline splitWith #-}++-- We can sneakily put our functor in the parameter "f" of @splitWith@ using the+-- @Compose@ newtype.+-- | An applicative version of @splitWith@.+splitWithA :: forall f g w n. (Applicative f, 1 <= w, 1 <= n) =>+ Endian ->+ (forall i. (i + w <= n * w) =>+ NatRepr (n * w) -> NatRepr i -> g (n * w) -> f (g w))+ {- ^ f function for slicing out f chunk of length @w@, starting at @i@ -} ->+ NatRepr n -> NatRepr w -> g (n * w) -> f (Vector n (g w))+splitWithA e select n w val = traverse getCompose $+ splitWith @(Compose f g) e select' n w $ Compose (pure val)+ where -- Wrap everything in Compose+ select' :: (forall i. (i + w <= n * w)+ => NatRepr (n * w) -> NatRepr i -> Compose f g (n * w) -> Compose f g w)+ -- Whatever we pass in as "val" is what's passed to select anyway,+ -- so there's no need to examine the argument. Just use "val" directly here.+ select' nw i _ = Compose $ select nw i val++newtype Vec a n = Vec (Vector n a)++vSlice :: (i + w <= l, 1 <= w) =>+ NatRepr w -> NatRepr l -> NatRepr i -> Vec a l -> Vec a w+vSlice w _ i (Vec xs) = Vec (slice i w xs)+{-# Inline vSlice #-}++-- | Append the two bit vectors. The first argument is+-- at the lower indexes of the resulting vector.+vAppend :: NatRepr n -> Vec a m -> Vec a n -> Vec a (m + n)+vAppend _ (Vec xs) (Vec ys) = Vec (append xs ys)+{-# Inline vAppend #-}++-- | Split a vector into a vector of vectors. The default ordering of+-- the outer result vector is "LittleEndian".+--+-- For example:+-- @+-- let wordsize = knownNat :: NatRepr 3+-- vecsize = knownNat :: NatRepr 12+-- numwords = knownNat :: NatRepr 4 (12 / 3)+-- Just inpvec = fromList vecsize [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ]+-- in show (split numwords wordsize inpvec) == "[ [1,2,3], [4,5,6], [7,8,9], [10,11,12] ]"+-- @+-- whereas a BigEndian result would have been+-- @+-- [ [10,11,12], [7,8,9], [4,5,6], [1,2,3] ]+-- @+split :: (1 <= w, 1 <= n) =>+ NatRepr n -- ^ Inner vector size+ -> NatRepr w -- ^ Outer vector size+ -> Vector (n * w) a -- ^ Input vector+ -> Vector n (Vector w a)+split n w xs = coerceVec (splitWith LittleEndian (vSlice w) n w (Vec xs))+{-# Inline split #-}++-- | Join a vector of vectors into a single vector. Assumes an+-- append/"LittleEndian" join strategy: the order of the inner vectors+-- is preserved in the result vector.+--+-- @+-- let innersize = knownNat :: NatRepr 4+-- Just inner1 = fromList innersize [ 1, 2, 3, 4 ]+-- Just inner2 = fromList innersize [ 5, 6, 7, 8 ]+-- Just inner3 = fromList innersize [ 9, 10, 11, 12 ]+-- outersize = knownNat :: NatRepr 3+-- Just outer = fromList outersize [ inner1, inner2, inner3 ]+-- in show (join innersize outer) = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ]+-- @+-- a prepend/"BigEndian" join strategy would have the result:+-- @+-- [ 9, 10, 11, 12, 5, 6, 7, 8, 1, 2, 3, 4 ]+-- @+join :: (1 <= w) => NatRepr w -> Vector n (Vector w a) -> Vector (n * w) a+join w xs = ys+ where Vec ys = joinWith vAppend w (coerceVec xs)+{-# Inline join #-}
+ src/Data/Parameterized/WithRepr.hs view
@@ -0,0 +1,115 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeSynonymInstances #-}+{-|+Copyright : (c) Galois, Inc 2019++This module declares a class with a single method that can be used to+derive a 'KnownRepr' constraint from an explicit 'Repr' argument.+Clients of this method need only create an empty instance. The default+implementation suffices.++For example, suppose we have defined a 'Repr' type for 'Peano' numbers:++@+data Peano = Z | S Peano++data PeanoRepr p where+ ZRepr :: PeanoRepr Z+ SRepr :: PeanoRepr p -> PeanoRepr (S p)++-- KnownRepr instances+@++Then the instance for this class+@+instance IsRepr PeanoRepr+@++means that functions with 'KnownRepr' constraints can be used after+pattern matching.++@+f :: KnownRepr PeanoRepr a => ...++example :: PeanoRepr n -> ...+example ZRepr = ...+example (SRepr (pm::PeanoRepr m)) = ... withRepr pm f ...+@+++NOTE: The type 'f' must be a *singleton* type--- i.e. for a given+type 'a' there should be only one value that inhabits 'f a'. If that+is not the case, this operation can be used to subvert coherence.++Credit: the unsafe implementation of 'withRepr' is taken from the+'withSingI' function in the singletons library+<http://hackage.haskell.org/package/singletons-2.5.1/>. Packaging+this method in a class here makes it more flexible---we do not have to+define a dedicated 'Sing' type, but can use any convenient singleton+as a 'Repr'.++NOTE: if this module is compiled without UNSAFE_OPS, the default+method will not be available.++-}+module Data.Parameterized.WithRepr(IsRepr(..)) where++import Data.Parameterized.Classes++#ifdef UNSAFE_OPS+import Data.Constraint(Dict(..))+import Unsafe.Coerce(unsafeCoerce)++import Data.Parameterized.NatRepr (NatRepr)+import Data.Parameterized.SymbolRepr (SymbolRepr)+import Data.Parameterized.Peano (PeanoRepr)+import Data.Parameterized.Context(Assignment)+import Data.Parameterized.List(List)+#else+import Data.Parameterized.Peano (PeanoRepr,PeanoView(..))+#endif+import Data.Parameterized.BoolRepr++-- | Turn an explicit Repr value into an implict KnownRepr constraint+class IsRepr (f :: k -> *) where++ withRepr :: f a -> (KnownRepr f a => r) -> r++#ifdef UNSAFE_OPS+ withRepr si r = case reprInstance si of+ Dict -> r++reprInstance :: forall f a . IsRepr f => f a -> Dict (KnownRepr f a)+reprInstance s = with_repr Dict+ where+ with_repr :: (KnownRepr f a => Dict (KnownRepr f a)) -> Dict (KnownRepr f a)+ with_repr si = unsafeCoerce (Don'tInstantiate si) s++newtype DI f a = Don'tInstantiate (KnownRepr f a => Dict (KnownRepr f a))+#endif+++------------------------------------+-- Instances for types defined in parameterized-utils++#ifdef UNSAFE_OPS+instance IsRepr NatRepr+instance IsRepr SymbolRepr+instance IsRepr PeanoRepr+instance IsRepr BoolRepr+instance IsRepr f => IsRepr (List f)+instance IsRepr f => IsRepr (Assignment f)+#else+-- awful, slow implementation for PeanoRepr+instance IsRepr PeanoRepr where+ withRepr ZRepr f = f+ withRepr (SRepr m) f = withRepr m f++instance IsRepr BoolRepr where+ withRepr TrueRepr f = f+ withRepr FalseRepr f = f+#endif
test/Test/Context.hs view
@@ -16,6 +16,7 @@ import Data.Parameterized.TraversableFC import Data.Parameterized.Some +import qualified Data.Parameterized.Context as C import qualified Data.Parameterized.Context.Safe as S import qualified Data.Parameterized.Context.Unsafe as U @@ -114,18 +115,13 @@ Just (Some idx_x) <- return $ U.intIndex i' (U.size x) Just (Some idx_y) <- return $ S.intIndex i' (S.size y) - let x' = over (ixF idx_x) twiddle x- y' = (ixF idx_y) %~ twiddle $ y- x'' = U.adjust twiddle idx_x x- y'' = S.adjust twiddle idx_y y+ let x' = x & ixF idx_x %~ twiddle+ y' = y & ixF idx_y %~ twiddle return (toListFC Some x' == toListFC Some y' && -- adjust actually modified the entry toListFC Some x /= toListFC Some x' &&- toListFC Some y /= toListFC Some y' &&- -- verify new version is equivalent to older deprecated version- toListFC Some x'' == toListFC Some x' &&- toListFC Some y'' == toListFC Some y')+ toListFC Some y /= toListFC Some y') , testProperty "update test" $ \v vs i -> ioProperty $ do let vals = v:vs -- ensures vals is not an empty array@@ -138,10 +134,8 @@ let x' = over (ixF idx_x) twiddle x y' = (ixF idx_y) %~ twiddle $ y- updX = set (ixF idx_x) (x' U.! idx_x) x- updY = (ixF idx_y) .~ (y' S.! idx_y) $ y- updX' = U.update idx_x (x' U.! idx_x) x- updY' = S.update idx_y (y' S.! idx_y) y+ updX = x & ixF idx_x .~ x' U.! idx_x+ updY = y & ixF idx_y .~ y' S.! idx_y return (toListFC Some updX == toListFC Some updY && -- update actually modified the entry@@ -149,10 +143,7 @@ toListFC Some y /= toListFC Some updY && -- update modified the expected entry toListFC Some x' == toListFC Some updX &&- toListFC Some y' == toListFC Some updY &&- -- verify new version is equivalent to older deprecated version- toListFC Some updX == toListFC Some updX' &&- toListFC Some updY == toListFC Some updY'+ toListFC Some y' == toListFC Some updY ) , testProperty "safe_eq" $ \vals1 vals2 -> ioProperty $ do@@ -167,4 +158,11 @@ case testEquality x y of Just Refl -> return $ vals1 == vals2 Nothing -> return $ vals1 /= vals2++ , testProperty "append_take" $ \vals1 vals2 -> ioProperty $ do+ Some x <- return $ mkUAsgn vals1+ Some y <- return $ mkUAsgn vals2+ let z = x U.<++> y+ let x' = C.take (U.size x) (U.size y) z+ return $ isJust $ testEquality x x' ]
+ test/Test/Vector.hs view
@@ -0,0 +1,70 @@+{-# Language DataKinds #-}+{-# Language ExplicitForAll #-}+{-# Language TypeOperators #-}+{-# Language TypeFamilies #-}+{-# Language FlexibleInstances #-}+{-# Language ScopedTypeVariables #-}+{-# Language StandaloneDeriving #-}+{-# Language CPP #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+#if __GLASGOW_HASKELL__ >= 805+{-# Language NoStarIsType #-}+#endif+module Test.Vector+( vecTests+) where++import Test.Tasty+import Test.Tasty.QuickCheck ( Arbitrary(..), testProperty, vectorOf )++import Data.Parameterized.NatRepr+import Data.Parameterized.Vector+import GHC.TypeLits+import Data.Semigroup+import Prelude hiding (reverse)+++instance KnownNat n => Arbitrary (NatRepr n) where+ arbitrary = return knownNat+++instance forall a n. ( 1 <= n+ , Arbitrary a+ , KnownNat n) =>+ Arbitrary (Vector n a) where+ arbitrary = do+ n <- arbitrary+ l <- vectorOf (widthVal n) arbitrary+ case fromList n l of+ Just v -> return v+ Nothing -> error ("fromList failure for size " <> show n)+++instance Show (Int -> Ordering) where+ show _ = "unshowable"++-- We use @Ordering@ just because it's simple+vecTests :: IO TestTree+vecTests = testGroup "Vector" <$> return+ [ testProperty "reverse100" $+ \n v -> fromList (n :: NatRepr 100) (v :: [Ordering]) ==+ (reverse <$> (reverse <$> (fromList n v)))+ , testProperty "reverseSingleton" $+ \n v -> fromList (n :: NatRepr 1) (v :: [Ordering]) ==+ (reverse <$> (fromList n v))+ , testProperty "split-join" $+ \n w v -> (v :: Vector (5 * 5) Ordering) ==+ (join (n :: NatRepr 5) $ split n (w :: NatRepr 5) $ v)+ -- @cons@ is the same for vectors or lists+ , testProperty "cons" $+ \n v x -> (cons x <$> fromList (n :: NatRepr 20) (v :: [Ordering])) ==+ (fromList (incNat n) (x:v))+ -- @snoc@ is like appending to a list+ , testProperty "snoc" $+ \n v x -> (flip snoc x <$> fromList (n :: NatRepr 20) (v :: [Ordering])) ==+ (fromList (incNat n) (v ++ [x]))+ -- @generate@ is like mapping a function over indices+ , testProperty "generate" $+ \n f -> Just (generate (n :: NatRepr 55) ((f :: Int -> Ordering) . widthVal)) ==+ (fromList (incNat n) (map f [0..widthVal n]) :: Maybe (Vector 56 Ordering))+ ]
test/UnitTest.hs view
@@ -4,6 +4,7 @@ import qualified Test.Context import qualified Test.NatRepr+import qualified Test.Vector main :: IO () main = tests >>= defaultMainWithIngredients ingrs@@ -19,4 +20,5 @@ tests = testGroup "ParameterizedUtils" <$> sequence [ Test.Context.contextTests , Test.NatRepr.natTests+ , Test.Vector.vecTests ]