diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,12 @@
 # Revision history for red-black-record
 
+## 2.1.6.0
+- Added ToRecord instance for Generically
+- Added module `TypeLevelRecordDot` in a secondary public library.
+
+## 2.1.5.0
+- Added cliftA_Record and cliftA2_Record.
+
 ## 2.1.4.0
 - Added trivial FromRecord and ToRecord instances to Record.
 
diff --git a/lib-dot/TypeLevelRecordDot.hs b/lib-dot/TypeLevelRecordDot.hs
new file mode 100644
--- /dev/null
+++ b/lib-dot/TypeLevelRecordDot.hs
@@ -0,0 +1,36 @@
+{-# LANGUAGE DataKinds,
+             TypeOperators,
+             TypeFamilies,
+             TypeApplications,
+             DeriveGeneric,
+             StandaloneDeriving,
+             DerivingStrategies,
+             UndecidableInstances,
+             KindSignatures,
+             PartialTypeSignatures,
+             FlexibleContexts,
+             ScopedTypeVariables,
+             StandaloneKindSignatures
+#-}
+-- | This module is for exploring record types in the REPL.
+module TypeLevelRecordDot (Dot) where
+
+import GHC.Generics (Generically(..))
+import Data.RBR
+import Data.Kind
+import GHC.TypeLits
+
+-- | Inspect the type of a field in a record
+--
+-- The idea is to use this type family in the REPL, using @kind!@ Mostly useful
+-- with complex parameterized records whose fields vary a lot according to the
+-- parameters.
+--
+-- If the record is at the "tip" of a function, the type family goes to the tip.
+--
+-- The records must have Generic instances.
+-- https://hachyderm.io/@DiazCarrete/112342828307643526 
+type Dot :: Type -> Symbol -> Type
+type family Dot r n where
+    Dot (a -> b) n = a -> Dot b n
+    Dot r n = Value n (RecordCode (Generically r))
diff --git a/lib/Data/RBR.hs b/lib/Data/RBR.hs
--- a/lib/Data/RBR.hs
+++ b/lib/Data/RBR.hs
@@ -74,6 +74,8 @@
        Maplike(..),
        cpure_Record,
        cpure'_Record,
+       cliftA_Record,
+       cliftA2_Record,
        prettyShow_Record,
        prettyShow_RecordI,
        prettyShow_Variant,
diff --git a/lib/Data/RBR/Examples.hs b/lib/Data/RBR/Examples.hs
--- a/lib/Data/RBR/Examples.hs
+++ b/lib/Data/RBR/Examples.hs
@@ -53,7 +53,7 @@
 >>> import Data.Proxy
 >>> import Data.Foldable
 >>> import Data.Monoid
->>> import Data.Profunctor (Star(..))
+>>> import Control.Arrow (Kleisli(..))
 >>> import GHC.Generics (Generic)
 >>> import GHC.TypeLits
 >>> import qualified Data.Text
@@ -168,7 +168,7 @@
 {- $json1
  
     We begin by creating a 'Record' of parsing functions, each paired with its
-    corresponding field name. We use 'Star' to treat the functions directly as
+    corresponding field name. We use 'Kleisli' to treat the functions directly as
     'Applicative's.
     
     Then we apply the transformation that we receive as parameter, which tweaks
@@ -186,14 +186,14 @@
               :: forall r c. (IsRecordType r c, 
                               Maplike c,
                               KeysValuesAll (KeyValueConstraints KnownSymbol FromJSON) c) 
-              => (Record ((,) String :.: Star Parser Data.Aeson.Value) c -> Record ((,) String :.: Star Parser Data.Aeson.Value) c)
+              => (Record ((,) String :.: Kleisli Parser Data.Aeson.Value) c -> Record ((,) String :.: Kleisli Parser Data.Aeson.Value) c)
               -> Data.Aeson.Value 
               -> Parser r
         parseSpecial transform = 
             let fieldParsers = transform $ 
-                    cpure'_Record (Proxy @FromJSON) $ \fieldName -> Comp (fieldName,Star parseJSON)
-                applyName (Comp (fieldName,Star f)) = Star (\o -> explicitParseField f o (Data.Text.pack fieldName))
-                Star objectParser = sequence_Record $ liftA_Record applyName fieldParsers
+                    cpure'_Record (Proxy @FromJSON) $ \fieldName -> Comp (fieldName,Kleisli parseJSON)
+                applyName (Comp (fieldName,Kleisli f)) = Kleisli (\o -> explicitParseField f o (fromString fieldName))
+                Kleisli objectParser = sequence_Record $ liftA_Record applyName fieldParsers
              in withObject "someobj" $ \o -> fromRecord <$> objectParser o
     :}
 
@@ -202,7 +202,7 @@
 >>> instance FromRecord Person 
 >>> :{ 
     instance FromJSON Person where 
-        parseJSON = parseSpecial (setField @"name" (Comp ("anothername",Star (\_ -> pure "foo"))))
+        parseJSON = parseSpecial (setField @"name" (Comp ("anothername",Kleisli (\_ -> pure "foo"))))
     :}
 
 >>> Data.Aeson.eitherDecode @Person (fromString "{ \"anothername\" : null, \"age\" : 50 }")
@@ -226,9 +226,9 @@
               -> Data.Aeson.Value 
               -> Parser r
         parseWithAliases aliases = 
-            let fieldParsers = cpure_Record (Proxy @(ValueConstraint FromJSON)) (Star parseJSON)
-                mapKSS (K name) (Star pf) = Star (\o -> explicitParseField pf o (Data.Text.pack name))
-                Star objectParser = sequence_Record $ liftA2_Record mapKSS aliases fieldParsers
+            let fieldParsers = cpure_Record (Proxy @(ValueConstraint FromJSON)) (Kleisli parseJSON)
+                mapKSS (K name) (Kleisli pf) = Kleisli (\o -> explicitParseField pf o (fromString name))
+                Kleisli objectParser = sequence_Record $ liftA2_Record mapKSS aliases fieldParsers
              in withObject "someobj" $ \o -> fromRecord <$> objectParser o
     :}
 
@@ -269,9 +269,9 @@
             let subparser = 
                     sequence_Record $
                         cpure'_Record (Proxy @FromJSON) $ \fieldName ->
-                            Star (\o -> explicitParseField parseJSON o (Data.Text.pack fieldName))
+                            Kleisli (\o -> explicitParseField parseJSON o (fromString fieldName))
                 intoOriginal subrecord = fromRecord (S.setFieldSubset @subset subrecord (toRecord r))
-                Star parser = intoOriginal <$> subparser
+                Kleisli parser = intoOriginal <$> subparser
              in withObject "someobj" parser
     :}
 
@@ -320,9 +320,9 @@
               -> Parser r
         parseAll = 
             let fieldParsers = cpure'_Record (Proxy @FromJSON) $ \fieldName -> 
-                    Star (\o -> explicitParseField parseJSON o (Data.Text.pack fieldName))
+                    Kleisli (\o -> explicitParseField parseJSON o (fromString fieldName))
                 injected = liftA2_Record (\f star -> K $ Alt $ runCase f . I <$> star) injections'_Variant fieldParsers 
-                Alt (Star parser) = collapse'_Record injected
+                Alt (Kleisli parser) = collapse'_Record injected
              in withObject "someobj" (\o -> fromVariant <$> parser o)
     :}
 
diff --git a/lib/Data/RBR/Internal.hs b/lib/Data/RBR/Internal.hs
--- a/lib/Data/RBR/Internal.hs
+++ b/lib/Data/RBR/Internal.hs
@@ -22,7 +22,9 @@
              DefaultSignatures,
              PartialTypeSignatures,
              LambdaCase,
-             EmptyCase 
+             EmptyCase,
+             StandaloneKindSignatures
+
 #-}
 {-#  OPTIONS_GHC -Wno-partial-type-signatures  #-}
 
@@ -38,7 +40,7 @@
 import           Data.List (intersperse)
 import           Data.Foldable (asum)
 import           GHC.TypeLits
-import           GHC.Generics (D1,C1,S1(..),M1(..),K1(..),Rec0(..))
+import           GHC.Generics (D1,C1,S1(..),M1(..),K1(..),Rec0(..), Generically(..))
 import qualified GHC.Generics as G
 
 import           Data.SOP (I(..),K(..),unI,unK,NP(..),NS(..),All,SListI,type (-.->)(Fn,apFn),mapKIK,(:.:)(..),Top)
@@ -79,13 +81,15 @@
 -- In fact, if I delete KeysValuesAllF and use eclusively KeysValuesAll, functions like demoteKeys seem to still work fine.
 --
 -- UndecidableSuperClasses and RankNTypes seem to be required by KeysValuesAllF.
+type KeysValuesAllF :: (symbol -> q -> Constraint) -> Map symbol q -> Constraint
 type family
-  KeysValuesAllF (c :: symbol -> q -> Constraint) (t :: Map symbol q) :: Constraint where
-  KeysValuesAllF  _ E                        = ()
-  KeysValuesAllF  c (N color left k v right) = (c k v, KeysValuesAll c left, KeysValuesAll c right)
+  KeysValuesAllF c t :: Constraint where
+  KeysValuesAllF _ E                        = ()
+  KeysValuesAllF c (N color left k v right) = (c k v, KeysValuesAll c left, KeysValuesAll c right)
 
 {- | Require a constraint for every key-value pair in a tree. This is a generalization of 'Data.SOP.All' from "Data.SOP".
 -}
+type KeysValuesAll :: (symbol -> q -> Constraint) -> Map symbol q -> Constraint
 class KeysValuesAllF c t => KeysValuesAll (c :: symbol -> q -> Constraint) (t :: Map symbol q) where
 
   --  'cpara_Map' constructs a 'Record' by means of a constraint for producing
@@ -100,6 +104,7 @@
 {- | This typeclass provides generalizations of 'Applicative'-like functions
      which work over 'Record's and 'Variant's.
 -}
+type Maplike :: Map Symbol Type -> Constraint
 class Maplike (t :: Map Symbol Type) where
     {- | 
          See 'cpure_Record' and 'cpure'_Record' for more useful versions of
@@ -240,7 +245,7 @@
 
     The naming scheme follows that of 'Data.SOP.NP.cpure_NP'.
  -}
-cpure_Record :: forall c t f. KeysValuesAll c t => (Proxy c) -> (forall k v. c k v => f v) -> Record f t
+cpure_Record :: forall c t f. KeysValuesAll c t => Proxy c -> (forall k v. c k v => f v) -> Record f t
 cpure_Record _ fpure = cpara_Map (Proxy @c) unit go
     where
     go :: forall left k' v' right color. (c k' v', KeysValuesAll c left, KeysValuesAll c right) 
@@ -259,7 +264,7 @@
 
     The naming scheme follows that of 'Data.SOP.NP.cpure_NP'.
  -}
-cpure'_Record :: forall c t f. KeysValuesAll (KeyValueConstraints KnownSymbol c) t => (Proxy c) -> (forall v. c v => String -> f v) -> Record f t
+cpure'_Record :: forall c t f. KeysValuesAll (KeyValueConstraints KnownSymbol c) t => Proxy c -> (forall v. c v => String -> f v) -> Record f t
 cpure'_Record _ fpure = cpara_Map (Proxy @(KeyValueConstraints KnownSymbol c)) unit go
    where
     go :: forall left k' v' right color. (KeyValueConstraints KnownSymbol c k' v', KeysValuesAll (KeyValueConstraints KnownSymbol c) left, KeysValuesAll (KeyValueConstraints KnownSymbol c) right) 
@@ -268,7 +273,37 @@
        -> Record f (N color left k' v' right)
     go left right = Node left (fpure @v' (symbolVal (Proxy @k'))) right 
 
+type F1 :: (q -> Type) -> (q -> Type) -> Map Symbol q -> Type
+newtype F1 f g t = F1 { unF1 :: Record f t -> Record g t }
 
+{- | Apply a transformation to the type constructor which wraps the fields of a 'Record', with some constraints in scope.
+ 
+     The naming scheme follows that of 'Data.SOP.NP.cliftA_NP'.
+-}
+cliftA_Record :: forall c t f g. KeysValuesAll c t => Proxy c -> (forall k v. c k v => f v -> g v) -> Record f t -> Record g t
+cliftA_Record _ func = unF1 $ cpara_Map (Proxy @c) (F1 $ \_ -> unit) go
+    where
+    go :: forall left k' v' right color. (c k' v', KeysValuesAll c left, KeysValuesAll c right) 
+       => F1 f g left
+       -> F1 f g right
+       -> F1 f g (N color left k' v' right)
+    go (F1 leftf) (F1 rightf) = F1 (\(Node left v right) -> Node (leftf left) (func @k' @v' v) (rightf right))
+
+type F2 :: (q -> Type) -> (q -> Type) -> (q -> Type) -> Map Symbol q -> Type
+newtype F2 f g h t = F2 { unF2 :: Record f t -> Record g t -> Record h t }
+
+{- | 
+     The naming scheme follows that of 'Data.SOP.NP.cliftA2_NP'.
+-}
+cliftA2_Record :: forall c t f g h. KeysValuesAll c t => Proxy c -> (forall k v. c k v => f v -> g v -> h v) -> Record f t -> Record g t -> Record h t
+cliftA2_Record _ func = unF2 $ cpara_Map (Proxy @c) (F2 $ \_ _ -> unit) go
+    where
+    go :: forall left k' v' right color. (c k' v', KeysValuesAll c left, KeysValuesAll c right) 
+       => F2 f g h left
+       -> F2 f g h right
+       -> F2 f g h (N color left k' v' right)
+    go (F2 leftf) (F2 rightf) = F2 (\(Node left1 v1 right1) (Node left2 v2 right2) -> Node (leftf left1 left2) (func @k' @v' v1 v2) (rightf right1 right2))
+
 {- | Create a 'Record' containing the names of each field. 
     
      The names are represented by a constant functor 'K' carrying an annotation
@@ -295,6 +330,7 @@
 
   Defined using the "class synonym" <https://www.reddit.com/r/haskell/comments/ab8ypl/monthly_hask_anything_january_2019/edk1ot3/ trick>.
 -}
+type KnownKey :: Symbol -> q -> Constraint
 class KnownSymbol k => KnownKey (k :: Symbol) (v :: q)
 instance KnownSymbol k => KnownKey k v 
 
@@ -321,6 +357,7 @@
 
   Defined using the "class synonym" <https://www.reddit.com/r/haskell/comments/ab8ypl/monthly_hask_anything_january_2019/edk1ot3/ trick>.
 -}
+type KnownKeyTypeableValue :: Symbol -> q -> Constraint
 class (KnownSymbol k, Typeable v) => KnownKeyTypeableValue (k :: Symbol) (v :: q)
 instance (KnownSymbol k, Typeable v) => KnownKeyTypeableValue k v 
 
@@ -329,6 +366,7 @@
 
   Defined using the "class synonym" <https://www.reddit.com/r/haskell/comments/ab8ypl/monthly_hask_anything_january_2019/edk1ot3/ trick>.
 -}
+type KeyValueConstraints :: (Symbol -> Constraint) -> (q -> Constraint) -> Symbol -> q -> Constraint
 class (kc k, vc v) => KeyValueConstraints (kc :: Symbol -> Constraint) (vc :: q -> Constraint) (k :: Symbol) (v :: q)
 instance (kc k, vc v) => KeyValueConstraints kc vc k v
 
@@ -337,6 +375,7 @@
 
   Defined using the "class synonym" <https://www.reddit.com/r/haskell/comments/ab8ypl/monthly_hask_anything_january_2019/edk1ot3/ trick>.
 -}
+type ValueConstraint :: (q -> Constraint) -> Symbol -> q -> Constraint
 class (vc v) => ValueConstraint (vc :: q -> Constraint) (k :: Symbol) (v :: q)
 instance (vc v) => ValueConstraint vc k v
 
@@ -350,7 +389,8 @@
 
      See also 'insert', 'delete' and 'project'.
 -}
-data Record (f :: q -> Type) (t :: Map Symbol q)  where
+type Record :: (q -> Type) -> Map Symbol q -> Type
+data Record (f :: q -> Type) (t :: Map Symbol q) where
     Empty :: Record f E 
     Node  :: Record f left -> f v -> Record f right -> Record f (N color left k v right)
 
@@ -419,6 +459,7 @@
 
      See also 'widen', 'winnow' and 'inject'.
 -}
+type Variant :: (q -> Type) -> Map Symbol q -> Type
 data Variant (f :: q -> Type) (t :: Map Symbol q)  where
     Here       :: f v -> Variant f (N color left k v right)
     LookRight  :: Variant f t -> Variant f (N color' left' k' v' t)
@@ -475,6 +516,7 @@
 
 {- | Insert a list of type level key / value pairs into a type-level map. 
 -}
+type InsertAll :: [(Symbol,q)] -> Map Symbol q -> Map Symbol q
 type family InsertAll (es :: [(Symbol,q)]) (t :: Map Symbol q) :: Map Symbol q where
     InsertAll '[] t = t
     InsertAll ( '(name,fieldType) ': es ) t = Insert name fieldType (InsertAll es t)
@@ -536,6 +578,7 @@
      If the map already has the key but with a /different/ type, the
      insertion fails to compile.
  -}
+type Insertable :: Symbol -> q -> Map Symbol q -> Constraint
 class Insertable (k :: Symbol) (v :: q) (t :: Map Symbol q) where
     type Insert k v t :: Map Symbol q
     _insert :: f v -> Record f t -> Record f (Insert k v t)
@@ -550,8 +593,8 @@
     _insert fv r = makeBlackR @_ (insert1 @_ @k @v fv r) 
     _widen v = makeBlackV @_ (widen1 @_ @k @v v)
 
-class CanMakeBlack (t :: Map Symbol k) where
-    type MakeBlack t :: Map Symbol k
+class CanMakeBlack (t :: Map Symbol q) where
+    type MakeBlack t :: Map Symbol q
     makeBlackR :: Record f t -> Record f (MakeBlack t)
     makeBlackV :: Variant f t -> Variant f (MakeBlack t)
 
@@ -568,6 +611,8 @@
     makeBlackR Empty = Empty
     makeBlackV = impossible
 
+-- for some reason, removing the "inline" kind signatures causes a compilation error
+type InsertableHelper1 :: Symbol -> q -> Map Symbol q -> Constraint
 class InsertableHelper1 (k :: Symbol) 
                         (v :: q) 
                         (t :: Map Symbol q) where
@@ -673,6 +718,7 @@
                    | DoNotBalance
                    deriving Show
 
+type ShouldBalance :: Map k' v' -> Map k' v' -> BalanceAction
 type family ShouldBalance (left :: Map k' v') (right :: Map k' v') :: BalanceAction where
     ShouldBalance (N R _ _ _ _) (N R _ _ _ _) = BalanceSpecial
     ShouldBalance (N R (N R _ _ _ _) _ _ _) _ = BalanceLL
@@ -803,6 +849,7 @@
 --
 {- | Auxiliary type family to avoid repetition and help improve compilation times.
  -}
+
 type family Field (f :: q -> Type) (t :: Map Symbol q) (v :: q) where
     Field f t v = Record f t -> (f v -> Record f t, f v)
 
@@ -977,6 +1024,7 @@
 
 {- | Represents a handler for a branch of a 'Variant'.  
 -}
+type Case :: (q -> Type) -> Type -> q -> Type
 newtype Case f a b = Case { runCase :: f b -> a }
 
 instance Functor f => Contravariant (Case f a) where
@@ -995,7 +1043,7 @@
 --
 --
 -- Subsetting
-
+type SetField :: (q -> Type) -> Type -> q -> Type
 newtype SetField f a b = SetField { getSetField :: f b -> a -> a }
  
 {- | For a given 'Map', produces a two-place constraint confirming the presence
@@ -1003,6 +1051,7 @@
      
      Defined using the "class synonym" <https://www.reddit.com/r/haskell/comments/ab8ypl/monthly_hask_anything_january_2019/edk1ot3/ trick>.
 -}
+type PresentIn :: Map Symbol q -> Symbol -> q -> Constraint
 class (Key k t, Value k t ~ v) => PresentIn (t :: Map Symbol q) (k :: Symbol) (v :: q) 
 instance (Key k t, Value k t ~ v) => PresentIn (t :: Map Symbol q) (k :: Symbol) (v :: q)
 
@@ -1123,6 +1172,7 @@
 
      The functions 'toNP' and 'fromNP' are usually easier to use. 
 -}
+type Productlike :: [k] -> Map Symbol k -> [k] -> Constraint
 class Productlike (start :: [k])
                   (t :: Map Symbol k) 
                   (result :: [k]) | start t -> result, result t -> start where
@@ -1190,6 +1240,7 @@
 
      The functions 'toNS' and 'fromNS' are usually easier to use. 
 -}
+type Sumlike :: [k] -> Map Symbol k -> [k] -> Constraint
 class Sumlike (start :: [k]) 
               (t :: Map Symbol k) 
               (result :: [k]) | start t -> result, result t -> start where
@@ -1294,7 +1345,7 @@
 --
 --
 -- Interfacing with normal records
-
+type ToRecord :: Type -> Constraint
 class ToRecord (r :: Type) where
     type RecordCode r :: Map Symbol Type
     -- https://stackoverflow.com/questions/22087549/defaultsignatures-and-associated-type-families/22088808
@@ -1303,6 +1354,14 @@
     default toRecord :: (G.Generic r,ToRecordHelper E (G.Rep r),RecordCode r ~ RecordCode' E (G.Rep r)) => r -> Record I (RecordCode r)
     toRecord r = toRecord' unit (G.from r)
 
+instance (
+    G.Generic r,
+    ToRecordHelper E (G.Rep r)
+    ) =>
+    ToRecord (Generically (r :: Type)) where
+    type RecordCode (Generically (r :: Type)) = RecordCode' E (G.Rep r)
+    toRecord (Generically r) = toRecord' unit (G.from r)
+
 class ToRecordHelper (start :: Map Symbol Type) (g :: Type -> Type) where
     type RecordCode' start g :: Map Symbol Type
     toRecord' :: Record I start -> g x -> Record I (RecordCode' start g)
@@ -1338,6 +1397,7 @@
 
 --
 --
+type FromRecord :: Type -> Constraint
 class ToRecord r => FromRecord (r :: Type) where
     fromRecord :: Record I (RecordCode r) -> r
     default fromRecord :: (G.Generic r, FromRecordHelper (RecordCode r) (G.Rep r)) => Record I (RecordCode r) -> r
@@ -1346,6 +1406,7 @@
 {- |
      The naming scheme follows that of 'Generics.SOP.IsProductType'.
  -}
+type IsRecordType :: Type -> Map Symbol Type -> Constraint
 type IsRecordType (r :: Type) (t :: Map Symbol Type) = (G.Generic r, ToRecord r, RecordCode r ~ t, FromRecord r)
 
 -- {- |
@@ -1354,6 +1415,7 @@
 -- fromRecordSuperset :: forall r subset whole flat. (FromRecord r, RecordCode r ~ subset, ProductlikeSubset subset whole flat) => Record I whole -> r
 -- fromRecordSuperset = fromRecord @r . projectSubset @subset @whole @flat
 
+type FromRecordHelper :: Map Symbol Type -> (Type -> Type) -> Constraint
 class FromRecordHelper (t :: Map Symbol Type) (g :: Type -> Type) where
     fromRecord' :: Record I t -> g x
 
@@ -1383,15 +1445,18 @@
 --
 --
 --
+type VariantCode :: Type -> Map Symbol Type
 type family VariantCode (s :: Type) :: Map Symbol Type where
     VariantCode s = VariantCode' E (G.Rep s)
 
+type VariantCode' :: Map Symbol Type -> (Type -> Type) -> Map Symbol Type
 type family VariantCode' (acc :: Map Symbol Type) (g :: Type -> Type) :: Map Symbol Type where
     VariantCode' acc (D1 meta fields) = VariantCode' acc fields
     VariantCode' acc (t1 G.:+: t2) = VariantCode' (VariantCode' acc t2) t1
     VariantCode' acc (C1 (G.MetaCons k _ _) (S1 ('G.MetaSel Nothing unpackedness strictness laziness) (Rec0 v))) = Insert k v acc
     VariantCode' acc (C1 (G.MetaCons k _ _) G.U1) = Insert k () acc
      
+type FromVariant :: Type -> Constraint     
 class FromVariant (s :: Type) where
     fromVariant :: Variant I (VariantCode s) -> s
     default fromVariant :: (G.Generic s, FromVariantHelper (VariantCode s) (G.Rep s)) => Variant I (VariantCode s) -> s
@@ -1402,6 +1467,7 @@
 {- |
      The naming scheme follows that of 'Generics.SOP.IsProductType'.
  -}
+type IsVariantType :: Type -> Map Symbol Type -> Constraint
 type IsVariantType (v :: Type) (t :: Map Symbol Type) = (G.Generic v, ToVariant v, VariantCode v ~ t, FromVariant v)
 
 class FromVariantHelper (t :: Map Symbol Type) (g :: Type -> Type) where
@@ -1437,6 +1503,7 @@
 
 --
 --
+type ToVariant :: Type -> Constraint
 class ToVariant (s :: Type) where
     toVariant :: s -> Variant I (VariantCode s)
     default toVariant :: (G.Generic s, ToVariantHelper (VariantCode s) (G.Rep s)) => s -> Variant I (VariantCode s)
@@ -1472,16 +1539,18 @@
 --
 --
 --
-
+type DiscriminateBalL :: Map k v -> Map k v -> Bool 
 type family DiscriminateBalL (l :: Map k v) (r :: Map k v) :: Bool where
     DiscriminateBalL (N R _ _ _ _) _ = False
     DiscriminateBalL _             _ = True
 
+type BalanceableL :: Map Symbol q -> Symbol -> q -> Map Symbol q -> Constraint
 class BalanceableL (l :: Map Symbol q) (k :: Symbol) (v :: q) (r :: Map Symbol q) where
     type BalL l k v r :: Map Symbol q
     balLR :: Record f (N color l k v r) -> Record f (BalL l k v r)
     balLV :: Variant f (N color l k v r) -> Variant f (BalL l k v r)
 
+type BalanceableHelperL :: Bool -> Map Symbol q -> Symbol -> q -> Map Symbol q -> Constraint
 class BalanceableHelperL (b :: Bool) (l :: Map Symbol q) (k :: Symbol) (v :: q) (r :: Map Symbol q) where
     type BalL' b l k v r :: Map Symbol q
     balLR' :: Record f (N color l k v r) -> Record f (BalL' b l k v r)
@@ -1543,15 +1612,19 @@
 -- balright a x (T R b y c) = T R a x (T B b y c)
 -- balright (T B a x b) y bl = balance (T R a x b) y bl
 -- balright (T R a x (T B b y c)) z bl = T R (balance (sub1 a) x b) y (T B c z bl)
+type DiscriminateBalR :: Map k v -> Map k v -> Bool
 type family DiscriminateBalR (l :: Map k v) (r :: Map k v) :: Bool where
     DiscriminateBalR _ (N R _ _ _ _) = False
     DiscriminateBalR _ _             = True
 
+
+type BalanceableR :: Map Symbol q -> Symbol -> q -> Map Symbol q -> Constraint
 class BalanceableR (l :: Map Symbol q) (k :: Symbol) (v :: q) (r :: Map Symbol q) where
     type BalR l k v r :: Map Symbol q
     balRR :: Record f (N color l k v r) -> Record f (BalR l k v r)
     balRV :: Variant f (N color l k v r) -> Variant f (BalR l k v r)
 
+type BalanceableHelperR :: Bool -> Map Symbol q -> Symbol -> q -> Map Symbol q -> Constraint
 class BalanceableHelperR (b :: Bool) (l :: Map Symbol q) (k :: Symbol) (v :: q) (r :: Map Symbol q) where
     type BalR' b l k v r :: Map Symbol q
     balRR' :: Record f (N color l k v r) -> Record f (BalR' b l k v r)
@@ -1623,6 +1696,7 @@
 -- app (T R a x b) c = T R a x (app b c)
 
 
+type Fuseable :: Map Symbol q -> Map Symbol q -> Constraint
 class Fuseable (l :: Map Symbol q) (r :: Map Symbol q) where
     type Fuse l r :: Map Symbol q
     fuseRecord :: Record f l -> Record f r -> Record f (Fuse l r)
@@ -1686,6 +1760,7 @@
     fuseRecord = fuseRecord1 @_ @(Fuse right1 left2) 
     fuseVariant = fuseVariant1 @_ @(Fuse right1 left2)
 
+type FuseableHelper1 :: Map Symbol q -> Map Symbol q -> Map Symbol q -> Constraint
 class FuseableHelper1 (fused :: Map Symbol q) (l :: Map Symbol q) (r :: Map Symbol q) where
     type Fuse1 fused l r :: Map Symbol q
     fuseRecord1 :: Record f l -> Record f r -> Record f (Fuse l r)
@@ -1851,6 +1926,8 @@
 --      | x<y = delformLeft a y b
 --      | x>y = delformRight a y b
 --      | otherwise = app a b
+-- removing the inline kind signatures here breaks stuff...
+type Delable :: Symbol -> q -> Map Symbol q -> Constraint
 class Delable (k :: Symbol) (v :: q) (t :: Map Symbol q) where
     type Del k v t :: Map Symbol q
     del :: Record f t -> Record f (Del k v t)
diff --git a/red-black-record.cabal b/red-black-record.cabal
--- a/red-black-record.cabal
+++ b/red-black-record.cabal
@@ -1,24 +1,23 @@
-cabal-version:       2.0
+cabal-version:       3.4
 name:                red-black-record
-version:             2.1.4.0
+version:             2.1.6.0
 synopsis:            Extensible records and variants indexed by a type-level Red-Black tree.
 
 description:         A library that provides extensible records and variants,
                      both indexed by a type-level red-black tree that maps
                      Symbol keys to value types of any kind. 
-                     .
+                      
                      The keys correspond to fields
                      names in records, and to branch names in variants.
-                     . 
+                       
                      At the term level, value types come wrapped in a type
                      constructor of kind @q -> Type@, where @q@ is the kind of
                      value types.
-                     .
                      The records and variants can be converted to and from
                      regular Haskell datatypes; also to and from the unlabelled
                      n-ary products and sums of the @sop-core@ package.
 
-license:             BSD3
+license:             BSD-3-Clause
 license-file:        LICENSE
 author:              Daniel Diaz
 maintainer:          diaz_carrete@yahoo.com
@@ -26,6 +25,7 @@
 extra-source-files:  CHANGELOG.md,
                      README.md
 build-type:          Simple
+tested-with: GHC ==9.8.1 || ==9.6.3
 
 source-repository head
     type: git
@@ -41,6 +41,14 @@
   hs-source-dirs:      lib
   default-language:    Haskell2010
 
+library dot
+  exposed-modules:     TypeLevelRecordDot
+  build-depends:       base                 >= 4.10.0.0 && < 5,
+                       red-black-record,
+  hs-source-dirs:      lib-dot
+  default-language:    Haskell2010
+  visibility: public
+
 library demoted
   exposed-modules:     Data.RBR.Demoted
   build-depends:       base                 >= 4.10.0.0 && < 5,
@@ -49,30 +57,28 @@
   hs-source-dirs:      lib-demoted
   default-language:    Haskell2010
 
-test-suite doctests
+test-suite tests
   type:                exitcode-stdio-1.0
   hs-source-dirs:      tests
-  ghc-options:         -threaded
-  main-is:             doctests.hs
-  build-depends:       base                 >= 4.10.0.0 && < 5,
+  main-is:             tests.hs
+  build-depends:
+                       base                 >= 4.10.0.0 && < 5,
                        sop-core             >= 0.4.0.0 && < 0.6,
+                       tasty                >= 0.10.1.1,
+                       tasty-hunit          >= 0.9.2,
                        red-black-record,
-                       aeson                >= 1.4.0.0 && < 1.5,
-                       bytestring           >= 0.10,
-                       text                 >= 1.1,
-                       profunctors          >= 5,
-                       doctest              >= 0.16.2
+                       red-black-record:demoted
   default-language:    Haskell2010
 
-test-suite tests
+test-suite tests-generically
   type:                exitcode-stdio-1.0
   hs-source-dirs:      tests
-  main-is:             tests.hs
+  main-is:             tests-generically.hs
   build-depends:
                        base                 >= 4.10.0.0 && < 5,
                        sop-core             >= 0.4.0.0 && < 0.6,
                        tasty                >= 0.10.1.1,
                        tasty-hunit          >= 0.9.2,
                        red-black-record,
-                       demoted
+                       red-black-record:dot,
   default-language:    Haskell2010
diff --git a/tests/doctests.hs b/tests/doctests.hs
deleted file mode 100644
--- a/tests/doctests.hs
+++ /dev/null
@@ -1,8 +0,0 @@
-import Test.DocTest
-
-main = doctest ["-ilib", 
-                "lib/Data/RBR.hs",
-                "lib/Data/RBR/Subset.hs",
-                "lib/Data/RBR/Examples.hs",
-                "lib/Data/RBR/Internal.hs"
-               ]
diff --git a/tests/tests-generically.hs b/tests/tests-generically.hs
new file mode 100644
--- /dev/null
+++ b/tests/tests-generically.hs
@@ -0,0 +1,59 @@
+{-# LANGUAGE DataKinds,
+             TypeOperators,
+             TypeFamilies,
+             TypeApplications,
+             DeriveGeneric,
+             StandaloneDeriving,
+             DerivingStrategies,
+             UndecidableInstances,
+             KindSignatures,
+             PartialTypeSignatures,
+             FlexibleContexts,
+             ScopedTypeVariables
+#-}
+{-# OPTIONS_GHC -Wno-partial-type-signatures #-}
+module Main where
+
+import Data.RBR
+import TypeLevelRecordDot
+
+import GHC.Generics (Generic, Generically(..))
+
+import Test.Tasty
+import Test.Tasty.HUnit (testCase,Assertion,assertEqual,assertBool)
+
+main :: IO ()
+main = defaultMain tests
+
+
+data Person = Person { 
+    personName :: String, 
+    address :: Address,
+    func :: Bool -> Int -> Address 
+    }
+    deriving stock (Generic)
+
+data Address = Address { 
+    street :: String, 
+    number :: Int, 
+    other :: Int
+    }
+    deriving stock (Generic)
+
+-- | Checking that 'Dot' has the proper associativity...
+foo :: Person `Dot` "address" `Dot` "number" 
+foo = 5
+
+foof :: Person `Dot` "func" `Dot` "number" 
+foof = \_ _ -> 3
+
+tests :: TestTree
+tests = testGroup "Tests" [ testCase "generically" testGenerically
+    ]
+
+testGenerically :: Assertion
+testGenerically = do
+    let r = Person "Foo" (Address "Somestreet" 1 2 ) (\_ _ -> Address "Somestreet" 1 2)
+        a = Data.RBR.getFieldI @"address" (Data.RBR.toRecord (Generically r))
+        n = Data.RBR.getFieldI @"number" (Data.RBR.toRecord (Generically a))
+    assertEqual "number" n 1
diff --git a/tests/tests.hs b/tests/tests.hs
--- a/tests/tests.hs
+++ b/tests/tests.hs
@@ -67,6 +67,10 @@
                             testGroup "polyKindedMap" [
                                     testCase "polyKinded01" polyKinded01,
                                     testCase "polyKinded02" polyKinded02
+                            ],
+                            testGroup "transformations" [
+                                    testCase "testLiftA_Record" cliftA2_01,
+                                    testCase "testLiftA2_Record" cliftA2_02
                             ]
                           ]
 
@@ -554,3 +558,30 @@
     return ()
 
 
+cliftA2_01 :: Assertion
+cliftA2_01 = do
+    let r = insertI @"foo" 'c'
+          . insertI @"bar" True
+          . insertI @"baz" (1::Int)
+          $ unit
+        r' = cliftA_Record (Proxy @(KeyValueConstraints KnownSymbol Show)) (\(I x) -> K (show x)) r
+        K foo = getField @"foo" r'
+        K bar = getField @"bar" r'
+        K baz = getField @"baz" r'
+    assertEqual "foo" foo "'c'"
+    assertEqual "bar" bar "True"
+    assertEqual "baz" baz "1"
+
+cliftA2_02 :: Assertion
+cliftA2_02 = do
+    let r = insertI @"foo" 'c'
+          . insertI @"bar" True
+          . insertI @"baz" (1::Int)
+          $ unit
+        r' = cliftA2_Record (Proxy @(KeyValueConstraints KnownSymbol Show)) (\(I x) (I y) -> K (show x ++ show y)) r r
+        K foo = getField @"foo" r'
+        K bar = getField @"bar" r'
+        K baz = getField @"baz" r'
+    assertEqual "foo" foo "'c''c'"
+    assertEqual "bar" bar "TrueTrue"
+    assertEqual "baz" baz "11"
