one-liner 0.5.2 → 0.6
raw patch · 10 files changed
+207/−883 lines, 10 filesdep +profunctorsdep ~basedep ~contravariantdep ~ghc-prim
Dependencies added: profunctors
Dependency ranges changed: base, contravariant, ghc-prim, transformers
Files
- examples/defaultsignature.hs +1/−1
- examples/realworld.hs +17/−21
- one-liner.cabal +7/−10
- src/Generics/OneLiner.hs +49/−156
- src/Generics/OneLiner/ADT.hs +0/−288
- src/Generics/OneLiner/ADT1.hs +0/−202
- src/Generics/OneLiner/Functions.hs +0/−114
- src/Generics/OneLiner/Functions1.hs +0/−52
- src/Generics/OneLiner/Info.hs +0/−39
- src/Generics/OneLiner/Internal.hs +133/−0
examples/defaultsignature.hs view
@@ -22,7 +22,7 @@ enumAll :: [t] default enumAll :: (ADT t, Constraints t EnumAll) => [t]- enumAll = concat $ createA (For :: For EnumAll) enumAll+ enumAll = concat $ createA (For :: For EnumAll) [enumAll] instance EnumAll Bool instance EnumAll a => EnumAll (Maybe a)
examples/realworld.hs view
@@ -3,12 +3,11 @@ import Generics.OneLiner import Data.Monoid-import Control.Lens (Traversal')-import Data.Typeable+-- import Control.Lens (Traversal')+-- import Data.Typeable import Control.DeepSeq import Test.SmallCheck.Series import Control.Monad.Logic.Class-import Control.Applicative import Control.Monad import Data.Hashable import Data.Functor.Contravariant@@ -18,16 +17,7 @@ import Test.QuickCheck.Arbitrary import Test.QuickCheck.Gen --- http://hackage.haskell.org/package/lens-4.3.3/docs/Generics-Deriving-Lens.html-whenCastableOrElse :: forall a b f. (Typeable a, Typeable b) => (b -> f b) -> (a -> f a) -> a -> f a-whenCastableOrElse f g = maybe g (\Refl -> f) (eqT :: Maybe (a :~: b)) -tinplate :: forall t b. (Typeable b, Deep Typeable t) => Traversal' t b-tinplate f- | isAtom (Proxy :: Proxy t) = f `whenCastableOrElse` pure- | otherwise = gtraverse (For :: For (Deep Typeable)) $ f `whenCastableOrElse` tinplate f-- -- http://hackage.haskell.org/package/deepseq-generics-0.1.1.1/docs/src/Control-DeepSeq-Generics.html -- This would work if the monoid instance of () would have been strict, now it doesn't... grnf :: (ADT t, Constraints t NFData) => t -> ()@@ -41,12 +31,12 @@ Fair fs <*> Fair as = Fair $ fs <~> as gseries :: forall t m. (ADT t, Constraints t (Serial m), MonadLogic m) => Series m t-gseries = foldr ((\/) . decDepth . runFair) mzero $ createA (For :: For (Serial m)) (Fair series)+gseries = foldr ((\/) . decDepth . runFair) mzero $ createA (For :: For (Serial m)) [Fair series] newtype CoSeries m a = CoSeries { runCoSeries :: forall r. Series m r -> Series m (a -> r) } instance Contravariant (CoSeries m) where contramap f (CoSeries g) = CoSeries $ fmap (. f) . g-instance MonadLogic m => Divisible (CoSeries m) where+instance Divisible (CoSeries m) where divide f (CoSeries g) (CoSeries h) = CoSeries $ \rs -> do rs' <- fixDepth rs f2 <- decDepthChecked (constM $ constM rs') (g $ h rs')@@ -70,11 +60,7 @@ -- http://hackage.haskell.org/package/binary-0.7.2.1/docs/Data-Binary.html gget :: (ADT t, Constraints t Binary) => Get t-gget = getWord8 >>= \ix -> createA (For :: For Binary) get !! fromEnum ix--instance Monoid Put where- mempty = return ()- mappend = (>>)+gget = getWord8 >>= \ix -> createA (For :: For Binary) [get] !! fromEnum ix gput :: (ADT t, Constraints t Binary) => t -> Put gput t = putWord8 (toEnum (ctorIndex t)) <> gfoldMap (For :: For Binary) put t@@ -89,9 +75,19 @@ conquer = CoArb $ const id instance Decidable CoArb where choose f (CoArb g) (CoArb h) = CoArb $ \a -> case f a of- Left b -> variant 0 . g b- Right c -> variant 1 . h c+ Left b -> variant (0::Int) . g b+ Right c -> variant (1::Int) . h c lose f = CoArb $ absurd . f gcoarbitrary :: (ADT t, Constraints t CoArbitrary) => t -> Gen b -> Gen b gcoarbitrary = unCoArb $ consume (For :: For CoArbitrary) (CoArb coarbitrary)+++-- -- http://hackage.haskell.org/package/lens-4.3.3/docs/Generics-Deriving-Lens.html+-- whenCastableOrElse :: forall a b f. (Typeable a, Typeable b) => (b -> f b) -> (a -> f a) -> a -> f a+-- whenCastableOrElse f g = maybe g (\Refl -> f) (eqT :: Maybe (a :~: b))+--+-- tinplate :: forall t b. (Typeable b, Deep Typeable t) => Traversal' t b+-- tinplate f+-- | isAtom (Proxy :: Proxy t) = f `whenCastableOrElse` pure+-- | otherwise = gtraverse (For :: For (Deep Typeable)) $ f `whenCastableOrElse` tinplate f
one-liner.cabal view
@@ -1,5 +1,5 @@ Name: one-liner-Version: 0.5.2+Version: 0.6 Synopsis: Constraint-based generics Description: Write short and concise generic instances of type classes. .@@ -27,17 +27,14 @@ Exposed-modules: Generics.OneLiner- Generics.OneLiner.ADT- Generics.OneLiner.ADT1- Generics.OneLiner.Functions- Generics.OneLiner.Functions1- Generics.OneLiner.Info+ Generics.OneLiner.Internal Build-depends:- base >= 4.7 && < 5- , transformers >= 0.3 && < 0.6- , contravariant >= 1.2 && < 1.4- , ghc-prim+ base >= 4.9 && < 5+ , transformers >= 0.5 && < 0.6+ , contravariant >= 1.4 && < 1.5+ , ghc-prim >= 0.5 && < 1.0+ , profunctors >= 5.2 && < 6.0 source-repository head type: git
src/Generics/OneLiner.hs view
@@ -13,17 +13,10 @@ -- ----------------------------------------------------------------------------- {-# LANGUAGE- GADTs- , DataKinds- , RankNTypes+ RankNTypes , TypeFamilies- , TypeOperators , ConstraintKinds , FlexibleContexts- , FlexibleInstances- , ScopedTypeVariables- , UndecidableInstances- , MultiParamTypeClasses #-} module Generics.OneLiner ( -- * Producing values@@ -36,181 +29,81 @@ consume, -- * Single constructor functions op0, op1, op2,+ -- * Generic programming with profunctors+ GenericProfunctor(..), generic, -- * Types- ADT, ADTRecord, ADTNonEmpty, CtorCount, Constraints, For(..), Deep, DeepConstraint, isAtom+ ADT, ADTRecord, ADTNonEmpty, CtorCount, Constraints, For(..) ) where import GHC.Generics-import GHC.Prim (Constraint)-import GHC.TypeLits import Control.Applicative import Data.Functor.Identity-import Data.Monoid-import Data.Proxy-import Data.Typeable import Data.Functor.Contravariant import Data.Functor.Contravariant.Divisible+import Data.Profunctor+import Generics.OneLiner.Internal -type family Constraints' (t :: * -> *) (c :: * -> Constraint) :: Constraint-type instance Constraints' V1 c = ()-type instance Constraints' U1 c = ()-type instance Constraints' (f :+: g) c = (Constraints' f c, Constraints' g c)-type instance Constraints' (f :*: g) c = (Constraints' f c, Constraints' g c)-type instance Constraints' (K1 i v) c = c v-type instance Constraints' (M1 i t f) c = Constraints' f c -class ADT' (t :: * -> *) where- type CtorCount' t :: Nat- type CtorCount' t = 1- ctorIndex' :: t x -> Int- ctorIndex' _ = 0- ctorCount :: proxy t -> Int- ctorCount _ = 1- f0 :: (Constraints' t c, Applicative f)- => for c -> (forall s. c s => f s) -> [f (t ())]- f1 :: (Constraints' t c, Applicative f)- => for c -> (forall s. c s => s -> f s) -> t x -> f (t x)- f2 :: (Constraints' t c, Applicative f)- => for c -> (forall s. c s => s -> s -> f s) -> t x -> t x -> Maybe (f (t x))- c0 :: (Constraints' t c, Decidable f)- => for c -> (forall s. c s => f s) -> f (t ())+newtype Zip f a b = Zip { runZip :: a -> a -> Maybe (f b) }+instance Functor f => Profunctor (Zip f) where+ dimap f g (Zip h) = Zip $ \a1 a2 -> fmap (fmap g) (h (f a1) (f a2))+instance Applicative f => GenericProfunctor (Zip f) where+ zero = Zip . const $ Just . pure+ unit = Zip . const $ Just . pure+ plus (Zip f) (Zip g) = Zip h where+ h (L1 a) (L1 b) = fmap (fmap L1) (f a b)+ h (R1 a) (R1 b) = fmap (fmap R1) (g a b)+ h _ _ = Nothing+ mult (Zip f) (Zip g) = Zip $ \(al :*: ar) (bl :*: br) -> liftA2 (:*:) <$> f al bl <*> g ar br -instance ADT' V1 where- type CtorCount' V1 = 0- ctorCount _ = 0- f0 _ _ = []- f1 _ _ = pure- f2 _ _ _ = Just . pure- c0 _ _ = lose (\v -> v `seq` undefined)+newtype Create f a b = Create { unCreate :: [f b] }+instance Functor f => Profunctor (Create f) where+ dimap _ f = Create . map (fmap f) . unCreate+instance Applicative f => GenericProfunctor (Create f) where+ zero = Create []+ unit = Create [pure U1]+ plus (Create l) (Create r) = Create $ map (fmap L1) l ++ map (fmap R1) r+ mult (Create l) (Create r) = Create $ liftA2 (:*:) <$> l <*> r -instance (ADT' f, ADT' g) => ADT' (f :+: g) where- type CtorCount' (f :+: g) = CtorCount' f + CtorCount' g- ctorIndex' (L1 l) = ctorIndex' l- ctorIndex' (R1 r) = ctorCount (Proxy :: Proxy f) + ctorIndex' r- ctorCount _ = ctorCount (Proxy :: Proxy f) + ctorCount (Proxy :: Proxy g)- f0 for f = map (fmap L1) (f0 for f) ++ map (fmap R1) (f0 for f)- f1 for f (L1 l) = L1 <$> f1 for f l- f1 for f (R1 r) = R1 <$> f1 for f r- f2 for f (L1 a) (L1 b) = fmap (fmap L1) (f2 for f a b)- f2 for f (R1 a) (R1 b) = fmap (fmap R1) (f2 for f a b)- f2 _ _ _ _ = Nothing- c0 for f = choose h (c0 for f) (c0 for f) where+newtype Consume f a b = Consume { unConsume :: f a }+instance Contravariant f => Profunctor (Consume f) where+ dimap f _ = Consume . contramap f . unConsume+instance Decidable f => GenericProfunctor (Consume f) where+ zero = Consume $ lose (\v -> v `seq` undefined)+ unit = Consume conquer+ plus (Consume f) (Consume g) = Consume $ choose h f g where h (L1 l) = Left l h (R1 r) = Right r+ mult (Consume f) (Consume g) = Consume $ divide (\(l :*: r) -> (l, r)) f g -instance ADT' U1 where- f0 _ _ = [pure U1]- f1 _ _ = pure- f2 _ _ _ = Just . pure- c0 _ _ = conquer -instance (ADT' f, ADT' g) => ADT' (f :*: g) where- f0 for f = [(:*:) <$> head (f0 for f) <*> head (f0 for f)]- f1 for f (l :*: r) = (:*:) <$> f1 for f l <*> f1 for f r- f2 for f (al :*: ar) (bl :*: br) = liftA2 (:*:) <$> f2 for f al bl <*> f2 for f ar br- c0 for f = divide (\(l :*: r) -> (l, r)) (c0 for f) (c0 for f)--instance ADT' (K1 i v) where- f0 _ f = [K1 <$> f]- f1 _ f (K1 v) = K1 <$> f v- f2 _ f (K1 l) (K1 r) = Just $ K1 <$> f l r- c0 _ f = contramap unK1 f--instance ADT' f => ADT' (M1 i t f) where- type CtorCount' (M1 i t f) = CtorCount' f- ctorIndex' = ctorIndex' . unM1- ctorCount _ = ctorCount (Proxy :: Proxy f)- f0 for f = map (fmap M1) (f0 for f)- f1 for f = fmap M1 . f1 for f . unM1- f2 for f (M1 l) (M1 r) = fmap (fmap M1) (f2 for f l r)- c0 for f = contramap unM1 (c0 for f)---- | `Constraints` is a constraint type synonym, containing the constraint requirements for an instance for `t` of class `c`.--- It requires an instance of class `c` for each component of `t`.-type Constraints t c = Constraints' (Rep t) c---- | `ADT` is a constraint type synonym. The `Generic` instance can be derived,--- and any generic representation will be an instance of `ADT'`.-type ADT t = (Generic t, ADT' (Rep t))---- | `CtorCount` is the number of constructors of a type at the type level.--- F.e. if you want to require that a type has at least two constructors,--- you can add the constraint @(2 `GHC.TypeLits.<=` `CtorCount` t)@.-type CtorCount t = CtorCount' (Rep t)---- | `ADTRecord` is a constraint type synonym. An instance is an `ADT` with *exactly* one constructor.-type ADTRecord t = (ADT t, 1 ~ CtorCount t)---- | `ADTNonEmpty` is a constraint type synonym. An instance is an `ADT` with *at least* one constructor.-type ADTNonEmpty t = (ADT t, 1 <= CtorCount t)---- | Tell the compiler which class we want to use in the traversal. Should be used like this:------ > (For :: For Show)------ Where @Show@ can be any class.-data For (c :: * -> Constraint) = For---- | @Deep c@ recursively requires all parts of the datatype to be an instance of `c` and of `Generic`.-class DeepConstraint c t => Deep (c :: * -> Constraint) t where-instance DeepConstraint c t => Deep c t---- http://stackoverflow.com/questions/14133121/can-i-constrain-a-type-family--- | A trick to avoid GHC from detecting a cycle.-type family DeepConstraint (c :: * -> Constraint) t :: Constraint-type instance DeepConstraint c t = (c t, ADT t, Constraints t (Deep c), Constraints t c)---- | For primitive values like `Int`, `Float`, `Double` and `Char`, the generic representation--- of a value contains itself. If you use generics recursively (f.e. using `Deep`),--- use `isAtom` to detect primitive values and prevent an infinite loop.-isAtom :: forall t proxy. (ADT t, Typeable t, Constraints t Typeable) => proxy t -> Bool-isAtom pt = case createA (For :: For Typeable) f :: [Const [Bool] t] of- [Const [True]] -> True- _ -> False- where- f :: forall a. Typeable a => Const [Bool] a- f = Const [tRep == typeRep (undefined :: [a])]- tRep = typeRep pt- -- | Create a value (one for each constructor), given how to construct the components. -- -- @--- `minBound` = `head` `$` `create` (`For` :: `For` `Bounded`) `minBound`--- `maxBound` = `last` `$` `create` (`For` :: `For` `Bounded`) `maxBound`+-- `minBound` = `head` `$` `create` (`For` :: `For` `Bounded`) [`minBound`]+-- `maxBound` = `last` `$` `create` (`For` :: `For` `Bounded`) [`maxBound`] -- @ create :: (ADT t, Constraints t c)- => for c -> (forall s. c s => s) -> [t]-create for f = map runIdentity (createA for (Identity f))+ => for c -> (forall s. c s => [s]) -> [t]+create for f = map runIdentity (createA for (Identity <$> f)) -- | Create a value (one for each constructor), given how to construct the components, under an applicative effect. -- -- Here's how to implement `get` from the `binary` package: -- -- @--- get = getWord8 `>>=` \\ix -> `createA` (`For` :: `For` Binary) get `!!` `fromEnum` ix+-- get = getWord8 `>>=` \\ix -> `createA` (`For` :: `For` Binary) [get] `!!` `fromEnum` ix -- @ createA :: (ADT t, Constraints t c, Applicative f)- => for c -> (forall s. c s => f s) -> [f t]-createA for f = map (fmap to) (f0 for f)+ => for c -> (forall s. c s => [f s]) -> [f t]+createA for f = unCreate $ generic for (Create f) -- | Generate ways to consume values of type `t`. This is the contravariant version of `createA`. consume :: (ADT t, Constraints t c, Decidable f) => for c -> (forall s. c s => f s) -> f t-consume for f = contramap from (c0 for f)+consume for f = unConsume $ generic for (Consume f) --- | Get the index in the lists returned by `create` and `createA` of the constructor of the given value.------ For example, this is the implementation of `put` that generates the binary data that--- the above implentation of `get` expects:------ @--- `put` t = `putWord8` (`toEnum` (`ctorIndex` t)) `<>` `gfoldMap` (`For` :: `For` `Binary`) `put` t--- @------ /Note that this assumes a straightforward `Monoid` instance of `Put` which `binary` unfortunately does not provide./-ctorIndex :: ADT t => t -> Int-ctorIndex = ctorIndex' . from -- | Map over a structure, updating each component. gmap :: (ADT t, Constraints t c)@@ -231,13 +124,13 @@ -- | Map each component of a structure to an action, evaluate these actions from left to right, and collect the results. gtraverse :: (ADT t, Constraints t c, Applicative f) => for c -> (forall s. c s => s -> f s) -> t -> f t-gtraverse for f = fmap to . f1 for f . from+gtraverse for f = runStar $ generic for (Star f) -- | Combine two values by combining each component of the structures with the given function. -- Returns `Nothing` if the constructors don't match. gzipWith :: (ADT t, Constraints t c)- => for c -> (forall s. c s => s -> s -> s) -> t -> t -> Maybe t-gzipWith for f l r = runIdentity <$> zipWithA for (\x y -> Identity (f x y)) l r+ => for c -> (forall s. c s => s -> s -> Maybe s) -> t -> t -> Maybe t+gzipWith for f l r = runIdentity <$> zipWithA for (\x y -> Identity <$> f x y) l r -- | Combine two values by combining each component of the structures to a monoid, and combine the results. -- Returns `mempty` if the constructors don't match.@@ -247,13 +140,13 @@ -- @ mzipWith :: (ADT t, Constraints t c, Monoid m) => for c -> (forall s. c s => s -> s -> m) -> t -> t -> m-mzipWith for f l r = maybe mempty getConst $ zipWithA for (\x y -> Const (f x y)) l r+mzipWith for f l r = maybe mempty getConst $ zipWithA for (\x y -> Just . Const $ f x y) l r -- | Combine two values by combining each component of the structures with the given function, under an applicative effect. -- Returns `Nothing` if the constructors don't match. zipWithA :: (ADT t, Constraints t c, Applicative f)- => for c -> (forall s. c s => s -> s -> f s) -> t -> t -> Maybe (f t)-zipWithA for f l r = fmap (fmap to) (f2 for f (from l) (from r))+ => for c -> (forall s. c s => s -> s -> Maybe (f s)) -> t -> t -> Maybe (f t)+zipWithA for f = runZip $ generic for (Zip f) -- | Implement a nullary operator by calling the operator for each component. --@@ -263,7 +156,7 @@ -- @ op0 :: (ADTRecord t, Constraints t c) => for c -> (forall s. c s => s) -> t-op0 for f = head $ create for f+op0 for f = head $ create for [f] -- | Implement a unary operator by calling the operator on the components. -- This is here for consistency, it is the same as `gmap`.@@ -283,6 +176,6 @@ -- @ op2 :: (ADTRecord t, Constraints t c) => for c -> (forall s. c s => s -> s -> s) -> t -> t -> t-op2 for f l r = case gzipWith for f l r of+op2 for f l r = case gzipWith for (\a b -> Just (f a b)) l r of Just t -> t Nothing -> error "op2: constructor mismatch should not be possible for ADTRecord"
− src/Generics/OneLiner/ADT.hs
@@ -1,288 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Generics.OneLiner.ADT--- License : BSD-style (see the file LICENSE)------ Maintainer : sjoerd@w3future.com--- Stability : experimental--- Portability : non-portable------ This module is for writing generic functions on algebraic data types--- of kind @*@. These data types must be an instance of the `ADT` type class.------ Here's an example how to write such an instance for this data type:------ @--- data T a = A Int a | B a (T a)--- @------ @--- instance `ADT` (T a) where--- `ctorIndex` A{} = 0--- `ctorIndex` B{} = 1--- `ctorInfo` _ 0 = `ctor` \"A\"--- `ctorInfo` _ 1 = `ctor` \"B\"--- type `Constraints` (T a) c = (c Int, c a, c (T a))--- `buildsRecA` _ sub rec =--- [ A `<$>` sub (`FieldInfo` (\\(A i _) -> i)) `<*>` sub (`FieldInfo` (\\(A _ a) -> a))--- , B `<$>` sub (`FieldInfo` (\\(B a _) -> a)) `<*>` rec (`FieldInfo` (\\(B _ t) -> t))--- ]--- @------ And this is how you would write generic equality, using the `All` monoid:------ @--- eqADT :: (`ADT` t, `Constraints` t `Eq`) => t -> t -> `Bool`--- eqADT s t = `ctorIndex` s == `ctorIndex` t `&&`--- `getAll` (`mbuilds` (`For` :: `For` `Eq`) (\\fld -> `All` $ s `!` fld `==` t `!` fld) \``at`\` s)--- @-------------------------------------------------------------------------------{-# LANGUAGE- RankNTypes- , TypeFamilies- , ConstraintKinds- , FlexibleInstances- , DefaultSignatures- , ScopedTypeVariables- #-}-module Generics.OneLiner.ADT (-- -- * Re-exports- module Generics.OneLiner.Info- , Constraint- -- | The kind of constraints-- -- * The @ADT@ type class- , ADT(..)- , ADTRecord(..)- , For(..)-- -- * Helper functions- , (!)- , at-- -- * Derived traversal schemes- , builds- , mbuilds- , gmap- , gfoldMap- , gtraverse-- -- ** ...for single constructor data types- , build- , op0- , op1- , op2-- ) where--import Generics.OneLiner.Info--import GHC.Prim (Constraint)-import Control.Applicative-import Data.Functor.Identity-import Data.Functor.Constant-import Data.Monoid--import Data.Maybe (fromJust)----- | Tell the compiler which class we want to use in the traversal. Should be used like this:------ > (For :: For Show)------ Where @Show@ can be any class.-data For (c :: * -> Constraint) = For---- | Type class for algebraic data types of kind @*@. Implement either `buildsA`--- if the type @t@ is not recursive, or `buildsRecA` if the type @t@ is recursive.-class ADT t where-- -- | Gives the index of the constructor of the given value in the list returned by `buildsA` and `buildsRecA`.- ctorIndex :: t -> Int- ctorIndex _ = 0-- -- | @ctorInfo n@ gives constructor information, f.e. its name, for the @n@th constructor.- -- The first argument is a dummy argument and can be @(undefined :: t)@.- ctorInfo :: t -> Int -> CtorInfo-- -- | The constraints needed to run `buildsA` and `buildsRecA`.- -- It should be a list of all the types of the subcomponents of @t@, each applied to @c@.- type Constraints t (c :: * -> Constraint) :: Constraint-- buildsA :: (Constraints t c, Applicative f)- => for c -- ^ Witness for the constraint @c@.- -> (forall s. c s => FieldInfo (t -> s) -> f s) -- ^ This function should return a value- -- for each subcomponent of @t@, wrapped in an applicative functor @f@. It is given- -- information about the field, which contains a projector function to get the subcomponent- -- from a value of type @t@. The type of the subcomponent is an instance of class @c@.- -> [f t] -- ^ A list of results, one for each constructor of type @t@. Each element is the- -- result of applicatively applying the constructor to the results of the given function- -- for each field of the constructor.-- default buildsA :: (c t, Constraints t c, Applicative f)- => for c -> (forall s. c s => FieldInfo (t -> s) -> f s) -> [f t]- buildsA for f = buildsRecA for f f-- buildsRecA :: (Constraints t c, Applicative f)- => for c -- ^ Witness for the constraint @c@.- -> (forall s. c s => FieldInfo (t -> s) -> f s) -- ^ This function should return a value- -- for each subcomponent of @t@, wrapped in an applicative functor @f@. It is given- -- information about the field, which contains a projector function to get the subcomponent- -- from a value of type @t@. The type of the subcomponent is an instance of class @c@.- -> (FieldInfo (t -> t) -> f t) -- ^ This function should return a value- -- for each subcomponent of @t@ that is itself of type @t@.- -> [f t] -- ^ A list of results, one for each constructor of type @t@. Each element is the- -- result of applicatively applying the constructor to the results of the given function- -- for each field of the constructor.- buildsRecA for sub _ = buildsA for sub-- {-# MINIMAL ctorInfo, (buildsA | buildsRecA) #-}---- | Add an instance for this class if the data type has exactly one constructor.------ This class has no methods.-class ADT t => ADTRecord t where---- | `buildsA` specialized to the `Identity` applicative functor.-builds :: (ADT t, Constraints t c)- => for c -> (forall s. c s => FieldInfo (t -> s) -> s) -> [t]-builds for f = runIdentity <$> buildsA for (Identity . f)---- | `buildsA` specialized to the `Constant` applicative functor, which collects monoid values @m@.-mbuilds :: forall t c m for. (ADT t, Constraints t c, Monoid m)- => for c -> (forall s. c s => FieldInfo (t -> s) -> m) -> [m]-mbuilds for f = getConstant <$> (buildsA for (Constant . f) :: [Constant m t])---- | Transform a value by transforming each subcomponent.-gmap :: (ADT t, Constraints t c)- => for c -> (forall s. c s => s -> s) -> t -> t-gmap for f t = builds for (\fld -> f (t ! fld)) `at` t---- | Fold a value, by mapping each subcomponent to a monoid value and collecting those.-gfoldMap :: (ADT t, Constraints t c, Monoid m)- => for c -> (forall s. c s => s -> m) -> t -> m-gfoldMap for f = getConstant . gtraverse for (Constant . f)---- | Applicative traversal given a way to traverse each subcomponent.-gtraverse :: (ADT t, Constraints t c, Applicative f)- => for c -> (forall s. c s => s -> f s) -> t -> f t-gtraverse for f t = buildsA for (\fld -> f (t ! fld)) `at` t---- | `builds` for data types with exactly one constructor-build :: (ADTRecord t, Constraints t c)- => for c -> (forall s. c s => FieldInfo (t -> s) -> s) -> t-build for f = head $ builds for f---- | Derive a 0-ary operation by applying the operation to every subcomponent.-op0 :: (ADTRecord t, Constraints t c) => for c -> (forall s. c s => s) -> t-op0 for op = build for (const op)---- | Derive a unary operation by applying the operation to every subcomponent.-op1 :: (ADTRecord t, Constraints t c) => for c -> (forall s. c s => s -> s) -> t -> t-op1 for op t = build for (\fld -> op $ t ! fld)---- | Derive a binary operation by applying the operation to every subcomponent.-op2 :: (ADTRecord t, Constraints t c) => for c -> (forall s. c s => s -> s -> s) -> t -> t -> t-op2 for op s t = build for (\fld -> (s ! fld) `op` (t ! fld))-----infixl 9 !--- | Get the subcomponent by using the projector from the field information.-(!) :: t -> FieldInfo (t -> s) -> s-t ! fld = project fld t---- | Get the value from the result of one of the @builds@ functions that matches the constructor of @t@.-at :: ADT t => [a] -> t -> a-at as t = as !! ctorIndex t----instance ADT () where-- type Constraints () c = ()- ctorInfo _ 0 = ctor "()"- buildsA _ _ = [ pure () ]--instance ADTRecord () where--instance ADT (a, b) where-- type Constraints (a, b) c = (c a, c b)- ctorInfo _ 0 = ctor "(,)"- buildsA _ f = [ (,) <$> f (FieldInfo fst) <*> f (FieldInfo snd) ]--instance ADTRecord (a, b) where--instance ADT (a, b, c) where-- type Constraints (a, b, c) tc = (tc a, tc b, tc c)- ctorInfo _ 0 = ctor "(,,)"- buildsA _ f = [(,,) <$> f (FieldInfo (\(a, _, _) -> a))- <*> f (FieldInfo (\(_, b, _) -> b))- <*> f (FieldInfo (\(_, _, c) -> c))- ]--instance ADTRecord (a, b, c) where--instance ADT (a, b, c, d) where-- type Constraints (a, b, c, d) tc = (tc a, tc b, tc c, tc d)- ctorInfo _ 0 = ctor "(,,,)"- buildsA _ f = [(,,,) <$> f (FieldInfo (\(a, _, _, _) -> a))- <*> f (FieldInfo (\(_, b, _, _) -> b))- <*> f (FieldInfo (\(_, _, c, _) -> c))- <*> f (FieldInfo (\(_, _, _, d) -> d))- ]--instance ADTRecord (a, b, c, d) where--instance ADT Bool where-- ctorIndex False = 0- ctorIndex True = 1- ctorInfo _ 0 = ctor "False"- ctorInfo _ 1 = ctor "True"-- type Constraints Bool c = ()- buildsA for _ = [ pure False, pure True ]--instance ADT (Either a b) where-- ctorIndex Left{} = 0- ctorIndex Right{} = 1- ctorInfo _ 0 = ctor "Left"- ctorInfo _ 1 = ctor "Right"-- type Constraints (Either a b) c = (c a, c b)- buildsA for f =- [ Left <$> f (FieldInfo (\(Left a) -> a))- , Right <$> f (FieldInfo (\(Right a) -> a))- ]--instance ADT (Maybe a) where-- ctorIndex Nothing = 0- ctorIndex Just{} = 1- ctorInfo _ 0 = ctor "Nothing"- ctorInfo _ 1 = ctor "Just"-- type Constraints (Maybe a) c = c a- buildsA for f =- [ pure Nothing- , Just <$> f (FieldInfo fromJust)- ]--instance ADT [a] where-- ctorIndex [] = 0- ctorIndex (_:_) = 1- ctorInfo _ 0 = ctor "[]"- ctorInfo _ 1 = CtorInfo ":" False (Infix RightAssociative 5)-- type Constraints [a] c = (c a, c [a])- buildsRecA for sub rec =- [ pure []- , (:) <$> sub (FieldInfo head) <*> rec (FieldInfo tail)]
− src/Generics/OneLiner/ADT1.hs
@@ -1,202 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Generics.OneLiner.ADT1--- License : BSD-style (see the file LICENSE)------ Maintainer : sjoerd@w3future.com--- Stability : experimental--- Portability : non-portable------ This module is for writing generic functions on algebraic data types--- of kind @* -> *@.--- These data types must be an instance of the `ADT1` type class.------ Here's an example how to write such an instance for this data type:------ @--- data T a = A [a] | B a (T a)--- @------ @--- instance `ADT1` T where--- `ctorIndex` A{} = 0--- `ctorIndex` B{} = 1--- `ctorInfo` _ 0 = `ctor` \"A\"--- `ctorInfo` _ 1 = `ctor` \"B\"--- type `Constraints` T c = (c [], c T)--- `buildsRecA` _ par sub rec =--- [ A `<$>` sub (`component` (\\(A l) -> l)--- , B `<$>` par (`param` (\\(B a _) -> a)) `<*>` rec (`component` (\\(B _ t) -> t))--- ]--- @-------------------------------------------------------------------------------{-# LANGUAGE- RankNTypes- , TypeFamilies- , TypeOperators- , ConstraintKinds- , FlexibleInstances- , DefaultSignatures- , ScopedTypeVariables- #-}-module Generics.OneLiner.ADT1 (-- -- * Re-exports- module Generics.OneLiner.Info- , Constraint- -- | The kind of constraints-- -- * The @ADT1@ type class- , ADT1(..)- , ADT1Record(..)- , For(..)- , Extract(..)- , (:~>)(..)-- -- * Helper functions- , (!)- , (!~)- , at- , param- , component-- -- * Derived traversal schemes- , builds- , mbuilds- , build-- ) where--import Generics.OneLiner.Info--import GHC.Prim (Constraint)-import Control.Applicative-import Data.Functor.Identity-import Data.Functor.Constant-import Data.Monoid--import Data.Maybe (fromJust)---newtype f :~> g = Nat { getNat :: forall x. f x -> g x }-newtype Extract f = Extract { getExtract :: forall x. f x -> x }----- | Tell the compiler which class we want to use in the traversal. Should be used like this:------ > (For :: For Show)------ Where @Show@ can be any class.-data For (c :: (* -> *) -> Constraint) = For---- | Type class for algebraic data types of kind @* -> *@. Implement either `buildsA`--- if the type @t@ is not recursive, or `buildsRecA` if the type @t@ is recursive.-class ADT1 t where-- -- | Gives the index of the constructor of the given value in the list returned by `buildsA` and `buildsRecA`.- ctorIndex :: t a -> Int- ctorIndex _ = 0-- -- | @ctorInfo n@ gives constructor information, f.e. its name, for the @n@th constructor.- -- The first argument is a dummy argument and can be @(undefined :: t a)@.- ctorInfo :: t a -> Int -> CtorInfo-- -- | The constraints needed to run `buildsA` and `buildsRecA`.- -- It should be a list of all the types of the subcomponents of @t@, each applied to @c@.- type Constraints t (c :: (* -> *) -> Constraint) :: Constraint- buildsA :: (Constraints t c, Applicative f)- => for c -- ^ Witness for the constraint @c@.- -> (FieldInfo (Extract t) -> f b)- -> (forall s. c s => FieldInfo (t :~> s) -> f (s b))- -> [f (t b)]-- default buildsA :: (c t, Constraints t c, Applicative f)- => for c- -> (FieldInfo (Extract t) -> f b)- -> (forall s. c s => FieldInfo (t :~> s) -> f (s b))- -> [f (t b)]- buildsA for param sub = buildsRecA for param sub sub-- buildsRecA :: (Constraints t c, Applicative f)- => for c -- ^ Witness for the constraint @c@.- -> (FieldInfo (Extract t) -> f b)- -> (forall s. c s => FieldInfo (t :~> s) -> f (s b))- -> (FieldInfo (t :~> t) -> f (t b))- -> [f (t b)]- buildsRecA for param sub _ = buildsA for param sub-- {-# MINIMAL ctorInfo, (buildsA | buildsRecA) #-}---- | Add an instance for this class if the data type has exactly one constructor.------ This class has no methods.-class ADT1 t => ADT1Record t where---- | `buildsA` specialized to the `Identity` applicative functor.-builds :: (ADT1 t, Constraints t c)- => for c- -> (FieldInfo (Extract t) -> b)- -> (forall s. c s => FieldInfo (t :~> s) -> s b)- -> [t b]-builds for f g = runIdentity <$> buildsA for (Identity . f) (Identity . g)---- | `buildsA` specialized to the `Constant` applicative functor, which collects monoid values @m@.-mbuilds :: forall t c m for. (ADT1 t, Constraints t c, Monoid m)- => for c- -> (FieldInfo (Extract t) -> m)- -> (forall s. c s => FieldInfo (t :~> s) -> m)- -> [m]-mbuilds for f g = getConstant <$> (buildsA for (Constant . f) (Constant . g) :: [Constant m (t b)])---- | `builds` for data types with exactly one constructor-build :: (ADT1Record t, Constraints t c)- => for c- -> (FieldInfo (Extract t) -> b)- -> (forall s. c s => FieldInfo (t :~> s) -> s b)- -> t b-build for f g = head $ builds for f g---- | Get the value from the result of one of the @builds@ functions that matches the constructor of @t@.-at :: ADT1 t => [a] -> t b -> a-at as t = as !! ctorIndex t--param :: (forall a. t a -> a) -> FieldInfo (Extract t)-param f = FieldInfo (Extract f)--component :: (forall a. t a -> s a) -> FieldInfo (t :~> s)-component f = FieldInfo (Nat f)--infixl 9 !-(!) :: t a -> FieldInfo (Extract t) -> a-t ! info = getExtract (project info) t--infixl 9 !~-(!~) :: t a -> FieldInfo (t :~> s) -> s a-t !~ info = getNat (project info) t---instance ADT1 Maybe where-- ctorIndex Nothing = 0- ctorIndex Just{} = 1- ctorInfo _ 0 = ctor "Nothing"- ctorInfo _ 1 = ctor "Just"-- type Constraints Maybe c = ()- buildsA _ f _ =- [ pure Nothing- , Just <$> f (param fromJust)- ]--instance ADT1 [] where-- ctorIndex [] = 0- ctorIndex (_:_) = 1- ctorInfo _ 0 = ctor "[]"- ctorInfo _ 1 = CtorInfo ":" False (Infix RightAssociative 5)-- type Constraints [] c = c []- buildsRecA _ p _ r =- [ pure []- , (:) <$> p (param head) <*> r (component tail)- ]
− src/Generics/OneLiner/Functions.hs
@@ -1,114 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Generics.OneLiner.Functions--- License : BSD-style (see the file LICENSE)------ Maintainer : sjoerd@w3future.com--- Stability : experimental--- Portability : non-portable-------------------------------------------------------------------------------{-# LANGUAGE RankNTypes, ConstraintKinds, ScopedTypeVariables #-}-module Generics.OneLiner.Functions (- -- * For all instances- eqADT- , compareADT- , minBoundADT- , maxBoundADT- , showsPrecADT- , readPrecADT- -- * For datatypes with one constructor- , memptyADT- , mappendADT- , fromIntegerADT- ) where--import Generics.OneLiner.ADT-import Control.Applicative-import Data.Monoid--import Text.Read-import Control.Monad-import Control.Monad.Trans.State-import qualified Control.Monad.Trans.Class as T--eqADT :: (ADT t, Constraints t Eq) => t -> t -> Bool-eqADT s t = ctorIndex s == ctorIndex t &&- getAll (mbuilds (For :: For Eq) (\fld -> All $ s ! fld == t ! fld) `at` s)--compareADT :: (ADT t, Constraints t Ord) => t -> t -> Ordering-compareADT s t = compare (ctorIndex s) (ctorIndex t) <>- mbuilds (For :: For Ord) (\fld -> compare (s ! fld) (t ! fld)) `at` s--minBoundADT :: (ADT t, Constraints t Bounded) => t-minBoundADT = head $ builds (For :: For Bounded) (const minBound)--maxBoundADT :: (ADT t, Constraints t Bounded) => t-maxBoundADT = last $ builds (For :: For Bounded) (const maxBound)--showsPrecADT :: forall t. (ADT t, Constraints t Show) => Int -> t -> ShowS-showsPrecADT d t = inner fty- where- CtorInfo name rec fty = ctorInfo t (ctorIndex t)-- inner (Infix _ d') = showParen (d > d') $ let [f0, f1] = fields (d' + 1) in- f0 . showChar ' ' . showString name . showChar ' ' . f1- inner _ = showParen (d > 10) $ showString name . showChar ' ' . body-- body = if rec- then showChar '{' . conc (showString ", ") (fields 0) . showChar '}'- else conc (showString " ") (fields 11)-- fields d' = mbuilds (For :: For Show) (return . f d') `at` t-- f :: Show s => Int -> FieldInfo (t -> s) -> ShowS- f d' info = if rec- then showString (selectorName info) . showString " = " . showsPrec d' (t ! info)- else showsPrec d' (t ! info)-- conc sep = foldr1 (\g ss -> g . sep . ss)--readPrecADT :: forall t. (ADT t, Constraints t Read) => ReadPrec t-readPrecADT = parens (choice ctorReads)- where- ctorReads = ctorParse <$> zip (fmap (ctorInfo (undefined :: t)) [0..]) (buildsA (For :: For Read) fieldParse)-- ctorParse (CtorInfo name _ (Infix _ d), getFields) =- let flds = evalStateT getFields $ do { Symbol name' <- lexP; guard (name' == name) }- in prec d flds-- ctorParse (CtorInfo name rec _, getFields) =- let flds = evalStateT getFields (return ())- in prec (if rec then 11 else 10) $ do- Ident name' <- lexP- guard (name == name')- if rec then do- Punc "{" <- lexP- res <- flds- Punc "}" <- lexP- return res- else- flds-- -- StateT is used to parse an infix operator after the first field- fieldParse :: Read s => FieldInfo (t -> s) -> StateT (ReadPrec ()) ReadPrec s- fieldParse (SelectorInfo name _) = StateT $ \parseOp -> do- Ident name' <- lexP- guard (name == name')- Punc "=" <- lexP- res <- reset readPrec- parseOp- return (res, return ())- fieldParse _ = StateT $ \parseOp -> do- res <- step readPrec- parseOp- return (res, return ())---memptyADT :: (ADTRecord t, Constraints t Monoid) => t-memptyADT = op0 (For :: For Monoid) mempty--mappendADT :: (ADTRecord t, Constraints t Monoid) => t -> t -> t-mappendADT = op2 (For :: For Monoid) mappend--fromIntegerADT :: (ADTRecord t, Constraints t Num) => Integer -> t-fromIntegerADT i = op0 (For :: For Num) (fromInteger i)
− src/Generics/OneLiner/Functions1.hs
@@ -1,52 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Generics.OneLiner.Functions1--- License : BSD-style (see the file LICENSE)------ Maintainer : sjoerd@w3future.com--- Stability : experimental--- Portability : non-portable-------------------------------------------------------------------------------{-# LANGUAGE RankNTypes, ConstraintKinds, ScopedTypeVariables #-}-module Generics.OneLiner.Functions1 (- -- * For all instances- fmapADT- , foldMapADT- , traverseADT- -- * For datatypes with one constructor- , pureADT- , apADT- , bindADT- , mfixADT-) where--import Generics.OneLiner.ADT1-import Control.Applicative-import Control.Monad.Fix-import Data.Monoid-import Data.Foldable-import Data.Traversable--fmapADT :: (ADT1 t, Constraints t Functor) => (a -> b) -> t a -> t b-fmapADT f ta = builds (For :: For Functor) (\fld -> f (ta ! fld)) (\fld -> fmap f (ta !~ fld)) `at` ta--foldMapADT :: (ADT1 t, Constraints t Foldable, Monoid m) => (a -> m) -> t a -> m-foldMapADT f ta = mbuilds (For :: For Foldable) (\fld -> f (ta ! fld)) (\fld -> foldMap f (ta !~ fld)) `at` ta--traverseADT :: (ADT1 t, Constraints t Traversable, Applicative f) => (a -> f b) -> t a -> f (t b)-traverseADT f ta = buildsA (For :: For Traversable) (\fld -> f (ta ! fld)) (\fld -> traverse f (ta !~ fld)) `at` ta---- unfoldADT :: (ADT1 t, Constraints t Unfoldable, Unfolder f) => f a -> f (t a)--- unfoldADT fa = choose $ buildsA (For :: For Unfoldable) (const fa) (const $ unfold fa)--pureADT :: (ADT1Record t, Constraints t Applicative) => a -> t a-pureADT a = build (For :: For Applicative) (const a) (const $ pure a)--apADT :: (ADT1Record t, Constraints t Applicative) => t (a -> b) -> t a -> t b-apADT tf ta = build (For :: For Applicative) (\fld -> (tf ! fld) (ta ! fld)) (\fld -> (tf !~ fld) <*> (ta !~ fld))--bindADT :: (ADT1Record t, Constraints t Monad) => t a -> (a -> t b) -> t b-bindADT ta f = build (For :: For Monad) (\fld -> f (ta ! fld) ! fld) (\fld -> (ta !~ fld) >>= ((!~ fld) . f))--mfixADT :: (ADT1Record t, Constraints t MonadFix) => (a -> t a) -> t a-mfixADT f = build (For :: For MonadFix) (\fld -> fix ((! fld) . f)) (\fld -> mfix ((!~ fld) . f))
− src/Generics/OneLiner/Info.hs
@@ -1,39 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Generics.OneLiner.Info--- License : BSD-style (see the file LICENSE)------ Maintainer : sjoerd@w3future.com--- Stability : experimental--- Portability : non-portable-------------------------------------------------------------------------------module Generics.OneLiner.Info where--data CtorInfo = CtorInfo- { ctorName :: String- , isRecord :: Bool- , fixity :: Fixity- }- deriving (Eq, Show, Ord, Read)--ctor :: String -> CtorInfo-ctor name = CtorInfo name False Prefix--data Fixity = Prefix | Infix Associativity Int- deriving (Eq, Show, Ord, Read)--data Associativity = LeftAssociative | RightAssociative | NotAssociative- deriving (Eq, Show, Ord, Read)--data FieldInfo p- = SelectorInfo- { selectorName :: String- , project :: p- }- | FieldInfo- { project :: p- }--instance Functor FieldInfo where- fmap f (SelectorInfo s p) = SelectorInfo s (f p)- fmap f (FieldInfo p) = FieldInfo (f p)
+ src/Generics/OneLiner/Internal.hs view
@@ -0,0 +1,133 @@+-----------------------------------------------------------------------------+-- |+-- Module : Generics.OneLiner.Internal+-- License : BSD-style (see the file LICENSE)+--+-- Maintainer : sjoerd@w3future.com+-- Stability : experimental+-- Portability : non-portable+--+-----------------------------------------------------------------------------+{-# LANGUAGE+ GADTs+ , DataKinds+ , RankNTypes+ , LambdaCase+ , TypeFamilies+ , TypeOperators+ , ConstraintKinds+ , FlexibleContexts+ , ScopedTypeVariables+ , UndecidableInstances+ #-}+module Generics.OneLiner.Internal where++import GHC.Generics+import GHC.Types (Constraint)+import GHC.TypeLits+import Data.Proxy+import Data.Profunctor++type family Constraints' (t :: * -> *) (c :: * -> Constraint) :: Constraint+type instance Constraints' V1 c = ()+type instance Constraints' U1 c = ()+type instance Constraints' (f :+: g) c = (Constraints' f c, Constraints' g c)+type instance Constraints' (f :*: g) c = (Constraints' f c, Constraints' g c)+type instance Constraints' (M1 i t f) c = Constraints' f c+type instance Constraints' (K1 i a) c = c a++class ADT' (t :: * -> *) where+ type CtorCount' t :: Nat+ type CtorCount' t = 1+ ctorIndex' :: t x -> Int+ ctorIndex' _ = 0+ ctorCount :: proxy t -> Int+ ctorCount _ = 1++ p :: (Constraints' t c, GenericProfunctor p)+ => for c -> (forall s. c s => p s s) -> p (t x) (t x)++instance ADT' V1 where+ type CtorCount' V1 = 0+ ctorCount _ = 0+ p _ _ = zero++instance (ADT' f, ADT' g) => ADT' (f :+: g) where+ type CtorCount' (f :+: g) = CtorCount' f + CtorCount' g+ ctorIndex' (L1 l) = ctorIndex' l+ ctorIndex' (R1 r) = ctorCount (Proxy :: Proxy f) + ctorIndex' r+ ctorCount _ = ctorCount (Proxy :: Proxy f) + ctorCount (Proxy :: Proxy g)+ p for f = plus (p for f) (p for f)++instance ADT' U1 where+ p _ _ = unit++instance (ADT' f, ADT' g) => ADT' (f :*: g) where+ p for f = mult (p for f) (p for f)++instance ADT' (K1 i v) where+ p _ = dimap unK1 K1++instance ADT' f => ADT' (M1 i t f) where+ type CtorCount' (M1 i t f) = CtorCount' f+ ctorIndex' = ctorIndex' . unM1+ ctorCount _ = ctorCount (Proxy :: Proxy f)+ p for f = dimap unM1 M1 (p for f)+++class Profunctor p => GenericProfunctor p where+ zero :: p (V1 a) (V1 a)+ unit :: p (U1 a) (U1 a)+ plus :: p (f a) (f' a) -> p (g a) (g' a) -> p ((f :+: g) a) ((f' :+: g') a)+ mult :: p (f a) (f' a) -> p (g a) (g' a) -> p ((f :*: g) a) ((f' :*: g') a)++instance Applicative f => GenericProfunctor (Star f) where+ zero = Star pure+ unit = Star pure+ plus (Star f) (Star g) = Star $ \case+ L1 l -> L1 <$> f l+ R1 r -> R1 <$> g r+ mult (Star f) (Star g) = Star $ \(l :*: r) -> (:*:) <$> f l <*> g r++-- | All the above functions have been implemented using this single function,+-- using different `profunctor`s.+generic :: (ADT t, Constraints t c, GenericProfunctor p)+ => for c -> (forall s. c s => p s s) -> p t t+generic for f = dimap from to $ p for f++-- | `Constraints` is a constraint type synonym, containing the constraint requirements for an instance for `t` of class `c`.+-- It requires an instance of class `c` for each component of `t`.+type Constraints t c = Constraints' (Rep t) c++-- | `ADT` is a constraint type synonym. The `Generic` instance can be derived,+-- and any generic representation will be an instance of `ADT'`.+type ADT t = (Generic t, ADT' (Rep t))++-- | `CtorCount` is the number of constructors of a type at the type level.+-- F.e. if you want to require that a type has at least two constructors,+-- you can add the constraint @(2 `GHC.TypeLits.<=` `CtorCount` t)@.+type CtorCount t = CtorCount' (Rep t)++-- | `ADTRecord` is a constraint type synonym. An instance is an `ADT` with *exactly* one constructor.+type ADTRecord t = (ADT t, 1 ~ CtorCount t)++-- | `ADTNonEmpty` is a constraint type synonym. An instance is an `ADT` with *at least* one constructor.+type ADTNonEmpty t = (ADT t, 1 <= CtorCount t)++-- | Tell the compiler which class we want to use in the traversal. Should be used like this:+--+-- > (For :: For Show)+--+-- Where @Show@ can be any class.+data For (c :: * -> Constraint) = For++-- | Get the index in the lists returned by `create` and `createA` of the constructor of the given value.+--+-- For example, this is the implementation of `put` that generates the binary data that+-- the above implentation of `get` expects:+--+-- @+-- `put` t = `putWord8` (`toEnum` (`ctorIndex` t)) `<>` `gfoldMap` (`For` :: `For` `Binary`) `put` t+-- @+ctorIndex :: ADT t => t -> Int+ctorIndex = ctorIndex' . from