one-liner 0.4.1 → 0.5
raw patch · 2 files changed
+24/−16 lines, 2 files
Files
- one-liner.cabal +1/−1
- src/Generics/OneLiner.hs +23/−15
one-liner.cabal view
@@ -1,5 +1,5 @@ Name: one-liner-Version: 0.4.1+Version: 0.5 Synopsis: Constraint-based generics Description: Write short and concise generic instances of type classes. .
src/Generics/OneLiner.hs view
@@ -14,6 +14,7 @@ ----------------------------------------------------------------------------- {-# LANGUAGE GADTs+ , DataKinds , RankNTypes , TypeFamilies , TypeOperators@@ -36,14 +37,16 @@ -- * Single constructor functions op0, op1, op2, -- * Types- ADT, ADTRecord, Constraints, For(..), Deep, DeepConstraint, isAtom+ ADT, ADTRecord, ADTNonEmpty, CtorCount, Constraints, For(..), Deep, DeepConstraint, isAtom ) 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@@ -57,9 +60,11 @@ 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 x) -> Int+ ctorCount :: proxy t -> Int ctorCount _ = 1 f0 :: (Constraints' t c, Applicative f) => for c -> (forall s. c s => f s) -> [f (t ())]@@ -71,6 +76,7 @@ => for c -> (forall s. c s => f s) -> f (t ()) instance ADT' V1 where+ type CtorCount' V1 = 0 ctorCount _ = 0 f0 _ _ = [] f1 _ _ = pure@@ -78,9 +84,10 @@ c0 _ _ = lose (\v -> v `seq` undefined) 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 (undefined :: [f ()]) + ctorIndex' r- ctorCount _ = ctorCount (undefined :: [f ()]) + ctorCount (undefined :: [g ()])+ 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@@ -110,21 +117,14 @@ 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 (undefined :: [M1 i t f ()])+ 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) -class ADTRecord' (f :: * -> *) where-instance ADTRecord' U1-instance ADTRecord' (f :*: g)-instance ADTRecord' (K1 i v)-instance ADTRecord' f => ADTRecord' (M1 i t f)-instance ADTRecord' f => ADTRecord' (V1 :+: f)-instance ADTRecord' f => ADTRecord' (f :+: V1)- -- | `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@@ -133,8 +133,16 @@ -- and any generic representation will be an instance of `ADT'`. type ADT t = (Generic t, ADT' (Rep t)) --- | `ADTRecord` is a constraint type synonym. An instance is an `ADT` with exactly one constructor.-type ADTRecord t = (ADT t, ADTRecord' (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: --