packages feed

predicate-typed 0.7.4.1 → 0.7.4.2

raw patch · 27 files changed

+600/−455 lines, 27 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Predicate.Data.Condition: instance forall k1 (prt :: k1) (n :: GHC.Types.Nat) k2 (p :: k2). GHC.Show.Show (Predicate.Data.Condition.GuardsN prt n p)
- Predicate.Data.Condition: instance forall k1 k2 x a (prt :: k1) (n :: GHC.Types.Nat) (p :: k2). (x GHC.Types.~ [a], Predicate.Core.P (Predicate.Data.Condition.GuardsNT prt n p) x) => Predicate.Core.P (Predicate.Data.Condition.GuardsN prt n p) x
- Predicate.Data.Enum: instance forall k1 (t :: k1) k2 (def :: k2). GHC.Show.Show (Predicate.Data.Enum.ToEnumBDef' t def)
- Predicate.Data.Enum: instance forall k1 k2 (def :: k1) (t :: k2) a. (Predicate.Core.P def (Data.Proxy.Proxy (Predicate.Core.PP t a)), Predicate.Core.PP def (Data.Proxy.Proxy (Predicate.Core.PP t a)) GHC.Types.~ Predicate.Core.PP t a, GHC.Show.Show a, GHC.Show.Show (Predicate.Core.PP t a), GHC.Enum.Bounded (Predicate.Core.PP t a), GHC.Enum.Enum (Predicate.Core.PP t a), GHC.Real.Integral a) => Predicate.Core.P (Predicate.Data.Enum.ToEnumBDef' t def) a
- Predicate.Data.Extra: data IList
- Predicate.Data.Extra: data IMap p q
- Predicate.Data.Extra: data PartitionsBy p q r
- Predicate.Data.Extra: instance GHC.Show.Show Predicate.Data.Extra.IList
- Predicate.Data.Extra: instance Predicate.Core.P Predicate.Data.Extra.IListT x => Predicate.Core.P Predicate.Data.Extra.IList x
- Predicate.Data.Extra: instance forall k1 (p :: k1) k2 (q :: k2) k3 (r :: k3). GHC.Show.Show (Predicate.Data.Extra.PartitionsBy p q r)
- Predicate.Data.Extra: instance forall k1 (p :: k1) k2 (q :: k2). GHC.Show.Show (Predicate.Data.Extra.IMap p q)
- Predicate.Data.Extra: instance forall k1 k2 (p :: k1) (q :: k2) x. Predicate.Core.P (Predicate.Data.Extra.IMapT p q) x => Predicate.Core.P (Predicate.Data.Extra.IMap p q) x
- Predicate.Data.Extra: instance forall k1 k2 k3 (p :: k1) (q :: k2) (r :: k3) x. Predicate.Core.P (Predicate.Data.Extra.PartitionsByT p q r) x => Predicate.Core.P (Predicate.Data.Extra.PartitionsBy p q r) x
- Predicate.Data.Foldable: instance forall k (f :: * -> *) a (t :: k) x. (GHC.Show.Show (f a), Data.Typeable.Internal.Typeable (Predicate.Core.PP t x), GHC.Show.Show (Predicate.Core.PP t x), Control.Lens.Indexed.FoldableWithIndex (Predicate.Core.PP t x) f, x GHC.Types.~ f a, GHC.Show.Show a) => Predicate.Core.P (Predicate.Data.Foldable.IToList' t) x
- Predicate.Data.Foldable: instance forall k (t :: k). GHC.Show.Show (Predicate.Data.Foldable.IToList' t)
- Predicate.Data.Foldable: instance forall k1 k2 a (t :: * -> *) (p :: k1) x (n :: k2). (GHC.Show.Show a, GHC.Show.Show (t a), Predicate.Core.PP p x GHC.Types.~ t a, Predicate.Core.P p x, GHC.Real.Integral (Predicate.Core.PP n x), Predicate.Core.P n x, Data.Foldable.Foldable t) => Predicate.Core.P (Predicate.Data.Foldable.Cycle n p) x
- Predicate.Data.Numeric: instance forall k1 (t :: k1) k2 (n :: k2). GHC.Show.Show (Predicate.Data.Numeric.FromInteger' t n)
- Predicate.Data.Numeric: instance forall k1 (t :: k1) k2 (n :: k2). GHC.Show.Show (Predicate.Data.Numeric.FromIntegral' t n)
- Predicate.Data.Numeric: instance forall k1 k2 (t :: k1) a (n :: k2). (GHC.Num.Num (Predicate.Core.PP t a), GHC.Real.Integral (Predicate.Core.PP n a), Predicate.Core.P n a, GHC.Show.Show (Predicate.Core.PP t a)) => Predicate.Core.P (Predicate.Data.Numeric.FromInteger' t n) a
- Predicate.Data.Numeric: instance forall k1 k2 (t :: k1) a (n :: k2). (GHC.Num.Num (Predicate.Core.PP t a), GHC.Real.Integral (Predicate.Core.PP n a), Predicate.Core.P n a, GHC.Show.Show (Predicate.Core.PP t a), GHC.Show.Show (Predicate.Core.PP n a)) => Predicate.Core.P (Predicate.Data.Numeric.FromIntegral' t n) a
- Predicate.Data.Ordering: data Cmp (o :: OrderingP) p q
- Predicate.Data.Ordering: data CmpI (o :: OrderingP) p q
- Predicate.Data.Ordering: data OrdA
- Predicate.Data.Ordering: data OrdA' p q
- Predicate.Data.Ordering: instance GHC.Show.Show Predicate.Data.Ordering.OrdA
- Predicate.Data.Ordering: instance Predicate.Core.P (Predicate.Data.Ordering.OrdA' Predicate.Core.Id Predicate.Core.Id) x => Predicate.Core.P Predicate.Data.Ordering.OrdA x
- Predicate.Data.Ordering: instance forall k1 (p :: k1) k2 (q :: k2). GHC.Show.Show (Predicate.Data.Ordering.OrdA' p q)
- Predicate.Data.Ordering: instance forall k1 k2 (p :: k1) (q :: k2) x. Predicate.Core.P (Predicate.Data.Ordering.OrdAT' p q) x => Predicate.Core.P (Predicate.Data.Ordering.OrdA' p q) x
- Predicate.Misc: asProxyLeft :: proxy a -> proxy1 a -> proxy a
- Predicate.Misc: asProxyRight :: proxy a -> proxy1 a -> proxy1 a
- Predicate.Util: TT :: !ValP -> !Val a -> !String -> !Forest PE -> TT a
- Predicate.Util: [_ttForest] :: TT a -> !Forest PE
- Predicate.Util: [_ttString] :: TT a -> !String
- Predicate.Util: [_ttValP] :: TT a -> !ValP
- Predicate.Util: [_ttVal] :: TT a -> !Val a
- Predicate.Util: _False :: a ~ Bool => Prism' (Val a) ()
- Predicate.Util: _True :: a ~ Bool => Prism' (Val a) ()
- Predicate.Util: val2P :: Lens' (Val a) ValP
- Predicate.Util: val2PBool :: a ~ Bool => Lens' (Val a) ValP
+ Predicate.Core: evalEither :: forall opts p a. (OptC opts, Show (PP p a), P p a) => a -> Either String (PP p a)
+ Predicate.Core: unsafeEval :: forall opts p a. (HasCallStack, OptC opts, Show (PP p a), P p a) => a -> PP p a
+ Predicate.Data.Condition: instance forall (n :: GHC.Types.Nat) k1 (prt :: k1) k2 (p :: k2). GHC.Show.Show (Predicate.Data.Condition.GuardsN n prt p)
+ Predicate.Data.Condition: instance forall k1 k2 x a (prt :: GHC.Types.Nat) (n :: k1) (p :: k2). (x GHC.Types.~ [a], Predicate.Core.P (Predicate.Data.Condition.GuardsNT prt n p) x) => Predicate.Core.P (Predicate.Data.Condition.GuardsN prt n p) x
+ Predicate.Data.Enum: instance forall k1 (t :: k1) k2 (def :: k2) k3 (p :: k3). GHC.Show.Show (Predicate.Data.Enum.ToEnumBDef' t def p)
+ Predicate.Data.Enum: instance forall k1 k2 k3 (def :: k1) (t :: k2) a (p :: k3). (Predicate.Core.P def (Data.Proxy.Proxy (Predicate.Core.PP t a)), Predicate.Core.PP def (Data.Proxy.Proxy (Predicate.Core.PP t a)) GHC.Types.~ Predicate.Core.PP t a, GHC.Show.Show (Predicate.Core.PP t a), GHC.Show.Show a, GHC.Enum.Bounded (Predicate.Core.PP t a), GHC.Enum.Enum (Predicate.Core.PP t a), GHC.Real.Integral (Predicate.Core.PP p a), Predicate.Core.P p a) => Predicate.Core.P (Predicate.Data.Enum.ToEnumBDef' t def p) a
+ Predicate.Data.Foldable: instance forall k1 (t :: k1) k2 (p :: k2). GHC.Show.Show (Predicate.Data.Foldable.IToList' t p)
+ Predicate.Data.Foldable: instance forall k1 k2 (t :: k1) x (f :: * -> *) (p :: k2) a. (Data.Typeable.Internal.Typeable (Predicate.Core.PP t x), GHC.Show.Show (Predicate.Core.PP t x), Control.Lens.Indexed.FoldableWithIndex (Predicate.Core.PP t x) f, Predicate.Core.PP p x GHC.Types.~ f a, Predicate.Core.P p x, GHC.Show.Show x, GHC.Show.Show a) => Predicate.Core.P (Predicate.Data.Foldable.IToList' t p) x
+ Predicate.Data.Foldable: instance forall k1 k2 a (p :: k1) x (t :: * -> *) (n :: k2). (GHC.Show.Show a, Predicate.Core.PP p x GHC.Types.~ t a, Predicate.Core.P p x, GHC.Real.Integral (Predicate.Core.PP n x), Predicate.Core.P n x, Data.Foldable.Foldable t) => Predicate.Core.P (Predicate.Data.Foldable.Cycle n p) x
+ Predicate.Data.List: data IList
+ Predicate.Data.List: data IMap p q
+ Predicate.Data.List: data PartitionsBy p q r
+ Predicate.Data.List: instance GHC.Show.Show Predicate.Data.List.IList
+ Predicate.Data.List: instance Predicate.Core.P Predicate.Data.List.IListT x => Predicate.Core.P Predicate.Data.List.IList x
+ Predicate.Data.List: instance forall k1 (p :: k1) k2 (q :: k2) k3 (r :: k3). GHC.Show.Show (Predicate.Data.List.PartitionsBy p q r)
+ Predicate.Data.List: instance forall k1 (p :: k1) k2 (q :: k2). GHC.Show.Show (Predicate.Data.List.IMap p q)
+ Predicate.Data.List: instance forall k1 k2 (p :: k1) (q :: k2) x. Predicate.Core.P (Predicate.Data.List.IMapT p q) x => Predicate.Core.P (Predicate.Data.List.IMap p q) x
+ Predicate.Data.List: instance forall k1 k2 k3 (p :: k1) (q :: k2) (r :: k3) x. Predicate.Core.P (Predicate.Data.List.PartitionsByT p q r) x => Predicate.Core.P (Predicate.Data.List.PartitionsBy p q r) x
+ Predicate.Data.Numeric: instance forall k1 (t :: k1) k2 (p :: k2). GHC.Show.Show (Predicate.Data.Numeric.FromInteger' t p)
+ Predicate.Data.Numeric: instance forall k1 (t :: k1) k2 (p :: k2). GHC.Show.Show (Predicate.Data.Numeric.FromIntegral' t p)
+ Predicate.Data.Numeric: instance forall k1 k2 (t :: k1) a (p :: k2). (GHC.Num.Num (Predicate.Core.PP t a), GHC.Real.Integral (Predicate.Core.PP p a), Predicate.Core.P p a, GHC.Show.Show (Predicate.Core.PP t a)) => Predicate.Core.P (Predicate.Data.Numeric.FromInteger' t p) a
+ Predicate.Data.Numeric: instance forall k1 k2 (t :: k1) a (p :: k2). (GHC.Num.Num (Predicate.Core.PP t a), GHC.Real.Integral (Predicate.Core.PP p a), Predicate.Core.P p a, GHC.Show.Show (Predicate.Core.PP t a), GHC.Show.Show (Predicate.Core.PP p a)) => Predicate.Core.P (Predicate.Data.Numeric.FromIntegral' t p) a
+ Predicate.Data.Ordering: data Compare
+ Predicate.Data.Ordering: data Comparing p
+ Predicate.Data.Ordering: instance GHC.Show.Show Predicate.Data.Ordering.Compare
+ Predicate.Data.Ordering: instance Predicate.Core.P (Predicate.Data.Ordering.Comparing Predicate.Core.Id) x => Predicate.Core.P Predicate.Data.Ordering.Compare x
+ Predicate.Data.Ordering: instance forall k (p :: k) x. Predicate.Core.P (Predicate.Data.Ordering.ComparingT p) x => Predicate.Core.P (Predicate.Data.Ordering.Comparing p) x
+ Predicate.Data.Ordering: instance forall k (p :: k). GHC.Show.Show (Predicate.Data.Ordering.Comparing p)
+ Predicate.Data.Tuple: data FromITuple
+ Predicate.Data.Tuple: instance GHC.Show.Show Predicate.Data.Tuple.FromITuple
+ Predicate.Data.Tuple: instance Predicate.Misc.FromITupleC x => Predicate.Core.P Predicate.Data.Tuple.FromITuple x
+ Predicate.Misc: class FromITupleC x where {
+ Predicate.Misc: cycle' :: [a] -> [a]
+ Predicate.Misc: fromITupleC :: FromITupleC x => x -> FromITupleP x
+ Predicate.Misc: instance Predicate.Misc.FromITupleC ()
+ Predicate.Misc: instance Predicate.Misc.FromITupleC (a, ())
+ Predicate.Misc: instance Predicate.Misc.FromITupleC (a, (b, ()))
+ Predicate.Misc: instance Predicate.Misc.FromITupleC (a, (b, (c, ())))
+ Predicate.Misc: instance Predicate.Misc.FromITupleC (a, (b, (c, (d, ()))))
+ Predicate.Misc: instance Predicate.Misc.FromITupleC (a, (b, (c, (d, (e, ())))))
+ Predicate.Misc: instance Predicate.Misc.FromITupleC (a, (b, (c, (d, (e, (f, ()))))))
+ Predicate.Misc: instance Predicate.Misc.FromITupleC (a, (b, (c, (d, (e, (f, (g, ())))))))
+ Predicate.Misc: instance Predicate.Misc.FromITupleC (a, (b, (c, (d, (e, (f, (g, (h, ()))))))))
+ Predicate.Misc: instance Predicate.Misc.FromITupleC (a, (b, (c, (d, (e, (f, (g, (h, (i, ())))))))))
+ Predicate.Misc: instance Predicate.Misc.FromITupleC (a, (b, (c, (d, (e, (f, (g, (h, (i, (j, ()))))))))))
+ Predicate.Misc: instance Predicate.Misc.FromITupleC (a, (b, (c, (d, (e, (f, (g, (h, (i, (j, (k, ())))))))))))
+ Predicate.Misc: instance Predicate.Misc.FromITupleC (a, (b, (c, (d, (e, (f, (g, (h, (i, (j, (k, (l, ()))))))))))))
- Predicate.Data.Condition: data GuardsN prt (n :: Nat) p
+ Predicate.Data.Condition: data GuardsN (n :: Nat) prt p
- Predicate.Data.Enum: data ToEnumBDef' t def
+ Predicate.Data.Enum: data ToEnumBDef' t def p
- Predicate.Data.Foldable: data IToList' t
+ Predicate.Data.Foldable: data IToList' t p
- Predicate.Data.Numeric: data FromInteger' t n
+ Predicate.Data.Numeric: data FromInteger' t p
- Predicate.Data.Numeric: data FromIntegral' t n
+ Predicate.Data.Numeric: data FromIntegral' t p
- Predicate.Examples.Common: type Ip4op = GuardsN (PrintT "octet %d out of range 0-255 found %d" Id) 4 (0 <..> 255) >> 'True
+ Predicate.Examples.Common: type Ip4op = GuardsN 4 (PrintT "octet %d out of range 0-255 found %d" Id) (0 <..> 255) >> 'True
- Predicate.Refined3: type family MakeR3' opts p
+ Predicate.Refined3: type family MakeR3 p
- Predicate.Util: _Fail :: forall a_atyc. Prism' (Val a_atyc) String
+ Predicate.Util: _Fail :: forall a_auyf. Prism' (Val a_auyf) String
- Predicate.Util: _Val :: forall a_atyc a_audq. Prism (Val a_audq) (Val a_atyc) a_audq a_atyc
+ Predicate.Util: _Val :: forall a_auyf a_avdt. Prism (Val a_avdt) (Val a_auyf) a_avdt a_auyf
- Predicate.Util: ttForest :: forall a_audD. Lens' (TT a_audD) (Forest PE)
+ Predicate.Util: ttForest :: forall a_avdG. Lens' (TT a_avdG) (Forest PE)
- Predicate.Util: ttString :: forall a_audD. Lens' (TT a_audD) String
+ Predicate.Util: ttString :: forall a_avdG. Lens' (TT a_avdG) String

Files

predicate-typed.cabal view
@@ -4,10 +4,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: 27025abbd4f913bb4b084f90b828539a965ba7c0b7b1eaada9454db7c0542abe+-- hash: 1cbf6c9b513c819809aea5c7ba639f8270876d5ac8734ba14595ede9fbbc5a41  name:           predicate-typed-version:        0.7.4.1+version:        0.7.4.2 synopsis:       Predicates, Refinement types and Dsl description:    Please see the README on GitHub at <https://github.com/gbwey/predicate-typed#readme> category:       Data
src/Predicate/Core.hs view
@@ -34,11 +34,9 @@   , Pure
   , Coerce
   , OneP
-
- -- ** core class
-  , P(..)
+  , Swap
 
-  -- ** IO evaluation
+  -- ** impure evaluation
   , pan
   , panv
   , pa
@@ -51,6 +49,7 @@   , pz
   , run
   , runs
+  , unsafeEval
 
   -- ** pure evaluation
   , runP
@@ -60,6 +59,7 @@   , evalBoolHide
   , evalHide
   , evalQuick
+  , evalEither
 
  -- ** wrap, unwrap
   , Wrap
@@ -115,8 +115,9 @@   , type (&)
   , DoL
 
- -- ** miscellaneous
-  , Swap
+ -- ** core class
+  , P(..)
+
   ) where
 import Predicate.Misc
 import Predicate.Util
@@ -136,6 +137,7 @@ import Data.Coerce (Coercible)
 import Data.Tree.Lens (root)
 import qualified Text.Regex.PCRE.Heavy as RH
+import GHC.Stack (HasCallStack)
 -- $setup
 -- >>> :set -XDataKinds
 -- >>> :set -XTypeApplications
@@ -168,9 +170,8 @@               -> a
               -> m (TT (PP p a))
 evalBool p opts = fmap fixTTBool . eval p opts
--- evalBool p opts = (over (mapped . ttValBool) id) . eval p opts
 
-
+-- | A specialised form of 'eval' that returns the result or the error string on failure
 evalQuick :: forall opts p i
   . ( OptC opts
     , P p i
@@ -974,7 +975,7 @@   case oDebug opts of
     DZero -> pure ()
     _ -> unlessNullM (prtTree opts pp) putStrLn
-  return (_ttVal pp)
+  return (pp ^. ttVal)
 
 -- | run expression with multiple options in a list
 --
@@ -1113,7 +1114,7 @@                     if anyOf (ttForest . folded . root . peValP) (has _FailP) qq
                     then qq & ttForest %~ (hh pp:) -- we still need pp for context
                     else e
-          Right q -> mkNodeCopy opts qq (lit3 opts msg0 q "" (topMessageEgregious (_ttString qq))) [hh pp, hh qq]
+          Right q -> mkNodeCopy opts qq (lit3 opts msg0 q "" (topMessageEgregious (qq ^. ttString))) [hh pp, hh qq]
 
 -- | infixl version of 'Predicate.Core.>>'
 data p >>> q deriving Show
@@ -1136,10 +1137,9 @@ 
 topMessageEgregious :: String -> String
 topMessageEgregious s =
-  let ret = fromMaybe "" $ (RH.scan topMessageExtractRe s ^? _last . _2 . _last)
+  let ret = fromMaybe "" (RH.scan topMessageExtractRe s ^? _last . _2 . _last)
   in '{' : (if null ret then s else ret) <> "}"
 
-
 topMessageExtractRe :: RH.Regex
 topMessageExtractRe = [RH.re|^.*\{([^}]+)\}.*?|]
 
@@ -1164,6 +1164,7 @@         d = x ^. _Wrapped'
     in pure $ mkNode opts (Val d) (show3 opts msg0 d x) []
 
+-- | similar to 'Wrap' where @t@ points to the type
 data Wrap' t p deriving Show
 
 instance ( Show (PP p x)
@@ -1206,7 +1207,6 @@ -- Present Sum {getSum = 25} (Sum {getSum = 13} <> Sum {getSum = 12} = Sum {getSum = 25})
 -- Val (Sum {getSum = 25})
 --
-
 data Wrap (t :: Type) p deriving Show
 type WrapT (t :: Type) p = Wrap' (Hole t) p
 
@@ -1504,6 +1504,14 @@ -- >>> pz @(10 % 4 <..> 40 % 5) 33
 -- Val False
 --
+-- >>> pl @(Negate 7 <..> 20) (-4)
+-- True (-7 <= -4 <= 20)
+-- Val True
+--
+-- >>> pl @(Negate 7 <..> 20) 21
+-- False (21 <= 20)
+-- Val False
+--
 data p <..> q deriving Show
 infix 4 <..>
 
@@ -1662,20 +1670,6 @@                       mkNodeB opts True (msg1 <> " i=" ++ show i ++ " " <> topMessage tt) hhs
 
 -- | similar to 'fst'
---
--- >>> pz @Fst (10,"Abc")
--- Val 10
---
--- >>> pz @Fst (10,"Abc",'x')
--- Val 10
---
--- >>> pz @Fst (10,"Abc",'x',False)
--- Val 10
---
--- >>> pl @Fst (99,'a',False,1.3)
--- Present 99 (Fst 99 | (99,'a',False,1.3))
--- Val 99
---
 data L1 p deriving Show
 
 instance ( Show (ExtractL1T (PP p x))
@@ -1693,6 +1687,21 @@         let b = extractL1C p
         in mkNode opts (Val b) (show3 opts msg0 b p) [hh pp]
 
+-- | similar to 'fst'
+--
+-- >>> pz @Fst (10,"Abc")
+-- Val 10
+--
+-- >>> pz @Fst (10,"Abc",'x')
+-- Val 10
+--
+-- >>> pz @Fst (10,"Abc",'x',False)
+-- Val 10
+--
+-- >>> pl @Fst (99,'a',False,1.3)
+-- Present 99 (Fst 99 | (99,'a',False,1.3))
+-- Val 99
+--
 data Fst deriving Show
 type FstT = L1 Id
 
@@ -1701,17 +1710,6 @@   eval _ = eval (Proxy @FstT)
 
 -- | similar to 'snd'
---
--- >>> pz @Snd (10,"Abc")
--- Val "Abc"
---
--- >>> pz @Snd (10,"Abc",True)
--- Val "Abc"
---
--- >>> pl @Snd (99,'a',False,1.3)
--- Present 'a' (Snd 'a' | (99,'a',False,1.3))
--- Val 'a'
---
 data L2 p deriving Show
 
 instance ( Show (ExtractL2T (PP p x))
@@ -1729,6 +1727,18 @@         let b = extractL2C p
         in mkNode opts (Val b) (show3 opts msg0 b p) [hh pp]
 
+-- | similar to 'snd'
+--
+-- >>> pz @Snd (10,"Abc")
+-- Val "Abc"
+--
+-- >>> pz @Snd (10,"Abc",True)
+-- Val "Abc"
+--
+-- >>> pl @Snd (99,'a',False,1.3)
+-- Present 'a' (Snd 'a' | (99,'a',False,1.3))
+-- Val 'a'
+--
 data Snd deriving Show
 
 type SndT = L2 Id
@@ -1738,17 +1748,6 @@   eval _ = eval (Proxy @SndT)
 
 -- | similar to 3rd element in a n-tuple
---
--- >>> pz @Thd (10,"Abc",133)
--- Val 133
---
--- >>> pz @Thd (10,"Abc",133,True)
--- Val 133
---
--- >>> pl @Thd (99,'a',False,1.3)
--- Present False (Thd False | (99,'a',False,1.3))
--- Val False
---
 data L3 p deriving Show
 
 instance ( Show (ExtractL3T (PP p x))
@@ -1766,6 +1765,18 @@         let b = extractL3C p
         in mkNode opts (Val b) (show3 opts msg0 b p) [hh pp]
 
+-- | similar to 3rd element in a n-tuple
+--
+-- >>> pz @Thd (10,"Abc",133)
+-- Val 133
+--
+-- >>> pz @Thd (10,"Abc",133,True)
+-- Val 133
+--
+-- >>> pl @Thd (99,'a',False,1.3)
+-- Present False (Thd False | (99,'a',False,1.3))
+-- Val False
+--
 data Thd deriving Show
 type ThdT = L3 Id
 
@@ -1913,7 +1924,7 @@     case getValueLR NoInline opts msg0 qq [] of
       Left e -> pure e
       Right q -> do
-        case chkSize opts msg0 (toList q) [hh qq] of
+        case chkSize opts msg0 q [hh qq] of
           Left e -> pure e
           Right xs -> do
             ts <- zipWithM (\i a -> ((i, a),) <$> evalHide @p opts a) [0::Int ..] xs
@@ -2527,3 +2538,29 @@ instance P L33T x => P L33 x where
   type PP L33 x = PP L33T x
   eval _ = eval (Proxy @L33T)
+
+-- | for use with TH.Lift in a splice. returns a pure value or fails with a tree
+unsafeEval :: forall opts p a
+        . ( HasCallStack
+          , OptC opts
+          , Show (PP p a)
+          , P p a
+          )
+        => a
+        -> PP p a
+unsafeEval = either (error . ("\n" <>)) id . evalEither @opts @p
+
+-- | run a type level computation and returns the value or a tree with the error
+evalEither :: forall opts p a
+        . ( OptC opts
+          , Show (PP p a)
+          , P p a
+          )
+        => a
+        -> Either String (PP p a)
+evalEither a =
+  let opts = getOpt @opts
+      pp = runIdentity $ eval (Proxy @p) opts a
+  in case pp ^. ttVal of
+       Val r -> Right r
+       Fail {} -> Left $ prtTree opts pp
src/Predicate/Data/Char.hs view
@@ -233,7 +233,7 @@ -- True ((>>) True | {True (&*) True})
 -- Val True
 --
--- >>> pz @( '(IsControlAll, IsLatin1All , IsHexDigitAll , IsOctDigitAll , IsDigitAll , IsPunctuationAll , IsSeparatorAll , IsSpaceAll)) "abc134"
+-- >>> pz @('(IsControlAll, IsLatin1All , IsHexDigitAll , IsOctDigitAll , IsDigitAll , IsPunctuationAll , IsSeparatorAll , IsSpaceAll)) "abc134"
 -- Val (False,True,True,False,False,False,False,False)
 --
 -- >>> pl @(SplitAts [1,2,10] Id >> Para '[IsLowerAll, IsDigitAll, IsUpperAll]) "abdefghi"
src/Predicate/Data/Condition.hs view
@@ -292,7 +292,7 @@               Right b -> mkNode opts (Val b) (show3 opts msgbase0 b a) (hh rr : hh pp : verboseList opts qq)
           Right False -> do
             ee <- eval (Proxy @e) opts (a, Proxy @(PP q (PP r x)))
-            pure $ case getValueLR NoInline opts ("Case:otherwise failed" <> nullIf ":" (_ttString ee)) ee [hh rr, hh pp] of
+            pure $ case getValueLR NoInline opts ("Case:otherwise failed" <> nullIf ":" (ee ^. ttString)) ee [hh rr, hh pp] of
               Left e -> e
               Right b -> mkNode opts (Val b) (show3 opts msgbase0 b a) [hh rr, hh pp, hh ee]
 
@@ -529,11 +529,11 @@         n = getLen @ps
     case chkSize opts msg1 as [] of
       Left e -> pure e
-      Right _ ->
-        if n /= length as then
-           let msg2 = msg0 <> badLength as n
+      Right ws ->
+        if n /= length ws then
+           let msg2 = msg0 <> badLength ws n
            in pure $ mkNode opts (Fail msg2) "" []
-        else evalBool (Proxy @(BoolsImpl (LenT ps) ps)) opts as
+        else evalBool (Proxy @(BoolsImpl (LenT ps) ps)) opts ws
 
 data BoolsImpl (n :: Nat) (os :: [(k,k1)]) deriving Show
 
@@ -630,17 +630,6 @@   type PP (BoolsN prt n p) x = Bool
   eval _ = evalBool (Proxy @(BoolsNT prt n p))
 
--- | if a predicate fails then then the corresponding symbol and value will be passed to the print function
---
--- >>> pz @(GuardsDetail "%s invalid: found %d" '[ '("hours", Between 0 23 Id),'("minutes",Between 0 59 Id),'("seconds",Between 0 59 Id)]) [13,59,61]
--- Fail "seconds invalid: found 61"
---
--- >>> pz @(GuardsDetail "%s invalid: found %d" '[ '("hours", Between 0 23 Id),'("minutes",Between 0 59 Id),'("seconds",Between 0 59 Id)]) [27,59,12]
--- Fail "hours invalid: found 27"
---
--- >>> pz @(GuardsDetail "%s invalid: found %d" '[ '("hours", Between 0 23 Id),'("minutes",Between 0 59 Id),'("seconds",Between 0 59 Id)]) [23,59,12]
--- Val [23,59,12]
---
 data GuardsDetailImpl (ps :: [(k,k1)]) deriving Show
 
 instance ( [a] ~ x
@@ -656,6 +645,17 @@        in pure $ mkNode opts (Fail msg1) "" []
     else eval (Proxy @(GuardsImpl (LenT ps) ps)) opts as
 
+-- | if a predicate fails then then the corresponding symbol and value will be passed to the print function
+--
+-- >>> pz @(GuardsDetail "%s invalid: found %d" '[ '("hours", Between 0 23 Id),'("minutes",Between 0 59 Id),'("seconds",Between 0 59 Id)]) [13,59,61]
+-- Fail "seconds invalid: found 61"
+--
+-- >>> pz @(GuardsDetail "%s invalid: found %d" '[ '("hours", Between 0 23 Id),'("minutes",Between 0 59 Id),'("seconds",Between 0 59 Id)]) [27,59,12]
+-- Fail "hours invalid: found 27"
+--
+-- >>> pz @(GuardsDetail "%s invalid: found %d" '[ '("hours", Between 0 23 Id),'("minutes",Between 0 59 Id),'("seconds",Between 0 59 Id)]) [23,59,12]
+-- Val [23,59,12]
+--
 data GuardsDetail prt (ps :: [(k0,k1)]) deriving Show
 type GuardsDetailT prt (ps :: [(k0,k1)]) = GuardsDetailImpl (ToGuardsDetailT prt ps)
 
@@ -671,26 +671,30 @@ 
 -- | leverages 'RepeatT' for repeating predicates (passthrough method)
 --
--- >>> pz @(GuardsN (PrintT "id=%d must be between 0 and 255, found %d" Id) 4 (0 <..> 0xff)) [121,33,7,256]
+-- >>> pz @(GuardsN 4 (PrintT "id=%d must be between 0 and 255, found %d" Id) (0 <..> 0xff)) [121,33,7,256]
 -- Fail "id=3 must be between 0 and 255, found 256"
 --
--- >>> pz @(GuardsN (PrintT "id=%d must be between 0 and 255, found %d" Id) 4 (0 <..> 0xff)) [121,33,7,44]
+-- >>> pz @(GuardsN 4 (PrintT "id=%d must be between 0 and 255, found %d" Id) (0 <..> 0xff)) [121,33,7,44]
 -- Val [121,33,7,44]
 --
--- >>> pl @(GuardsN (PrintT "guard(%d) %d is out of range" Id) 4 (0 <..> 0xff)) [1,2,3,4]
+-- >>> pl @(GuardsN 4 (PrintT "guard(%d) %d is out of range" Id) (0 <..> 0xff)) [1,2,3,4]
 -- Present [1,2,3,4] (Guards(4))
 -- Val [1,2,3,4]
 --
--- >>> pl @(GuardsN (PrintT "guard(%d) %d is out of range" Id) 4 (0 <..> 0xff)) [1,2,3,4,5]
+-- >>> pl @(GuardsN 4 (PrintT "guard(%d) %d is out of range" Id) (0 <..> 0xff)) [1,2,3,4,5]
 -- Error Guards:invalid length(5) expected 4
 -- Fail "Guards:invalid length(5) expected 4"
 --
--- >>> pl @(GuardsN (PrintT "guard(%d) %d is out of range" Id) 4 (0 <..> 0xff)) [1,2,3]
+-- >>> pl @(GuardsN 4 (PrintT "guard(%d) %d is out of range" Id) (0 <..> 0xff)) [1,2,3]
 -- Error Guards:invalid length(3) expected 4
 -- Fail "Guards:invalid length(3) expected 4"
 --
-data GuardsN prt (n :: Nat) p deriving Show
-type GuardsNT prt (n :: Nat) p = Guards (ToGuardsT prt (RepeatT n p))
+-- >>> pl @(Resplit "\\." >> Map (ReadP Int Id) >> GuardsN 4 (PrintT "invalid pos=%d val=%d" Id) (0 <..> 0xff)) "13.22.44.1231"
+-- Error invalid pos=3 val=1231 (Guard(3) 1231 | [13,22,44,1231])
+-- Fail "invalid pos=3 val=1231"
+--
+data GuardsN (n :: Nat) prt p deriving Show
+type GuardsNT (n :: Nat) prt p = Guards (ToGuardsT prt (RepeatT n p))
 
 instance ( x ~ [a]
          , P (GuardsNT prt n p) x
src/Predicate/Data/Enum.hs view
@@ -389,27 +389,33 @@   type PP (ToEnum t) x = PP (ToEnumT t) x
   eval _ = eval (Proxy @(ToEnumT t))
 
-data ToEnumBDef' t def deriving Show
+-- | bounded 'toEnum' function where @t@ refers to location of the type and @p@ the location of the input
+data ToEnumBDef' t def p deriving Show
 
 instance ( P def (Proxy (PP t a))
          , PP def (Proxy (PP t a)) ~ PP t a
-         , Show a
          , Show (PP t a)
+         , Show a
          , Bounded (PP t a)
          , Enum (PP t a)
-         , Integral a
-         ) => P (ToEnumBDef' t def) a where
-  type PP (ToEnumBDef' t def) a = PP t a
+         , Integral (PP p a)
+         , P p a
+         ) => P (ToEnumBDef' t def p) a where
+  type PP (ToEnumBDef' t def p) a = PP t a
   eval _ opts a = do
     let msg0 = "ToEnumBDef"
-    case toEnumMay $ fromIntegral a of
-      Nothing -> do
-         let msg1 = msg0 <> " out of range"
-         pp <- eval (Proxy @def) opts (Proxy @(PP t a))
-         pure $ case getValueLR NoInline opts msg1 pp [] of
-           Left e -> e
-           Right _ -> mkNodeCopy opts pp msg1 [hh pp]
-      Just n -> pure $ mkNode opts (Val n) (show3 opts msg0 n a) []
+    pp <- eval (Proxy @p) opts a
+    case getValueLR NoInline opts msg0 pp [] of
+      Left e -> pure e
+      Right (fromIntegral -> p) -> do
+        case toEnumMay p of
+          Nothing -> do
+             let msg1 = msg0 <> " out of range"
+             dd <- eval (Proxy @def) opts (Proxy @(PP t a))
+             pure $ case getValueLR NoInline opts msg1 dd [hh pp] of
+               Left e -> e
+               Right _ -> mkNodeCopy opts dd msg1 [hh pp, hh dd]
+          Just n -> pure $ mkNode opts (Val n) (show3 opts msg0 n a) [hh pp]
 
 -- | bounded 'toEnum' function
 --
@@ -428,7 +434,7 @@ -- Val EQ
 --
 data ToEnumBDef (t :: Type) def deriving Show
-type ToEnumBDefT (t :: Type) def = ToEnumBDef' (Hole t) def
+type ToEnumBDefT (t :: Type) def = ToEnumBDef' (Hole t) def Id
 
 instance P (ToEnumBDefT t def) x => P (ToEnumBDef t def) x where
   type PP (ToEnumBDef t def) x = PP (ToEnumBDefT t def) x
@@ -448,7 +454,7 @@ -- Fail "ToEnum bounded"
 --
 data ToEnumBFail (t :: Type) deriving Show
-type ToEnumBFailT (t :: Type) = ToEnumBDef' (Hole t) (FailP "ToEnum bounded")
+type ToEnumBFailT (t :: Type) = ToEnumBDef' (Hole t) (FailP "ToEnum bounded") Id
 
 instance P (ToEnumBFailT t) x => P (ToEnumBFail t) x where
   type PP (ToEnumBFail t) x = PP (ToEnumBFailT t) x
src/Predicate/Data/Extra.hs view
@@ -20,22 +20,17 @@  -- ** list functions
     HeadDef
   , HeadFail
+  , HeadMay
   , TailDef
   , TailFail
+  , TailMay
   , LastDef
   , LastFail
+  , LastMay
   , InitDef
   , InitFail
-
-  , HeadMay
-  , LastMay
-  , TailMay
   , InitMay
 
-  , PartitionsBy
-  , IMap
-  , IList
-
  -- ** primes
   , IsPrime
   , PrimeNext
@@ -50,13 +45,11 @@ import Predicate.Core
 import Predicate.Misc
 import Predicate.Util
-import Predicate.Data.List (Head, Uncons, Unsnoc, SortBy, Zip, GroupBy, SortOn, ZipWith)
-import Predicate.Data.Enum (type (...))
-import Predicate.Data.Numeric (type (-))
+import Predicate.Data.List (Uncons, Unsnoc)
 import Predicate.Data.Maybe (JustDef, JustFail)
 import Predicate.Data.Lifted (FMap)
 import Control.Lens
-import qualified Safe (headNote, cycleNote)
+import qualified Safe (headNote)
 import Data.Proxy (Proxy(..))
 -- $setup
 -- >>> :set -XDataKinds
@@ -482,68 +475,11 @@     let msg0 = "IsLuhn"
     in pure $ case chkSize opts msg0 x [] of
          Left e -> e
-         Right _ ->
-          let xs = zipWith (*) (reverse x) (Safe.cycleNote msg0 [1,2])
+         Right ws ->
+          let xs = zipWith (*) (ws ^. reversed) (cycle' [1,2])
               ys = map (\w -> if w>=10 then w-9 else w) xs
               z = sum' ys
               ret = z `mod` 10
-          in if ret == 0 then mkNodeB opts True (msg0 <> " | " <> showL opts x) []
-             else mkNodeB opts False (msg0 <> " map=" <> showL opts ys <> " sum=" <> showL opts z <> " ret=" <> showL opts ret <> showVerbose opts " | " x) []
-
--- | experimental: sorts then partitions and then sorts each partitions based on the leftmost occurring value in the original list
---   if the existing order of data is fine then use 'Predicate.Data.List.GroupBy' as you do not need this
---
--- >>> pz @(PartitionsBy (Fst ==! Snd) (L11 == L21) Id) [10,9,9,1,9]
--- Val [[10],[9,9,9],[1]]
---
--- >>> pz @(PartitionsBy OrdA (L11 < L21) Id) "efaffabec"
--- Val ["a","f","f","abce","ef"]
---
--- >>> pz @(PartitionsBy 'GT 'True Id) "efaffabec"
--- Val ["cebaffafe"]
---
--- >>> pz @(PartitionsBy 'GT 'False Id) "efaffabec"
--- Val ["e","f","a","f","f","a","b","e","c"]
---
--- >>> pz @(PartitionsBy (Fst ==! Snd) (L12 > L22) Id) [10,9,9,1,9,4]
--- Val [[9],[1],[9,10],[4,9]]
---
--- >>> pz @(PartitionsBy (L11 ==! L21) (L12 > L22) Id) "eddadc"
--- Val ["d","a","de","cd"]
---
--- >>> pz @(PartitionsBy (L11 ==! L21) (L11 < L21) Id) [10,9,9,1,9,4]
--- Val [[9],[1,4,9],[9,10]]
---
-data PartitionsBy p q r deriving Show
-type PartitionsByT p q r = SortBy p (Zip r (0 ... (Length r - 1))) >> GroupBy q Id >> SortOn (Head >> Snd) Id >> Map (Map Fst)
-
-instance P (PartitionsByT p q r) x => P (PartitionsBy p q r) x where
-  type PP (PartitionsBy p q r) x = PP (PartitionsByT p q r) x
-  eval _ = eval (Proxy @(PartitionsByT p q r))
-
--- | add an index to map
---
--- >>> pz @(Rescan "^(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)$" >> Map (Snd >> IMap (GuardBool (PrintT "bad value=%d %s" Id) (Snd >> ReadP Int Id < 255)) Id)) "123.222.999.3"
--- Fail "bad value=2 999"
---
--- >>> pz @(Rescan "^(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)$" >> Map (Snd >> IMap (GuardBool (PrintT "bad value=%d %s" Id) (Snd >> ReadP Int Id < 255)) Id)) "123.222.99.3"
--- Val [[True,True,True,True]]
---
-data IMap p q deriving Show
-type IMapT p q = ZipWith p (0 ... (Length q - 1)) q
-
-instance P (IMapT p q) x => P (IMap p q) x where
-  type PP (IMap p q) x = PP (IMapT p q) x
-  eval _ = eval (Proxy @(IMapT p q))
-
--- | add an index to list
---
--- >>> pz @IList "abcdef"
--- Val [(0,'a'),(1,'b'),(2,'c'),(3,'d'),(4,'e'),(5,'f')]
---
-data IList deriving Show
-type IListT = Zip (0 ... (Len - 1)) Id
+          in if ret == 0 then mkNodeB opts True (msg0 <> " | " <> showL opts ws) []
+             else mkNodeB opts False (msg0 <> " map=" <> showL opts ys <> " sum=" <> showL opts z <> " ret=" <> showL opts ret <> showVerbose opts " | " ws) []
 
-instance P IListT x => P IList x where
-  type PP IList x = PP IListT x
-  eval _ = eval (Proxy @IListT)
src/Predicate/Data/Foldable.hs view
@@ -53,7 +53,6 @@ import Data.List.NonEmpty (NonEmpty(..))
 import qualified GHC.Exts as GE
 import Data.List (findIndex)
-import qualified Safe (cycleNote)
 -- $setup
 -- >>> import Predicate.Prelude
 -- >>> :set -XDataKinds
@@ -124,21 +123,31 @@     let b = has _Empty as
     in pure $ mkNodeB opts b ("IsEmpty" <> showVerbose opts " | " as) []
 
-data IToList' t deriving Show
+-- | explicit version of 'IToList' with an extra parameter @p@ to point to the value
+--
+-- >>> pz @(IToList' (Hole _) Snd) (True,"aBc" :: String)
+-- Val [(0,'a'),(1,'B'),(2,'c')]
+--
+data IToList' t p deriving Show
 
-instance ( Show (f a)
-         , Typeable (PP t x)
+instance ( Typeable (PP t x)
          , Show (PP t x)
          , FoldableWithIndex (PP t x) f
-         , x ~ f a
+         , PP p x ~ f a
+         , P p x
+         , Show x
          , Show a
-         ) => P (IToList' t) x where
-  type PP (IToList' t) x = [(PP t x, ExtractAFromTA x)]
-  eval _ opts x =
+         ) => P (IToList' t p) x where
+  type PP (IToList' t p) x = [(PP t x, ExtractAFromTA (PP p x))]
+  eval _ opts x = do
     let msg0 = "IToList"
-        b = itoList x
         t = showT @(PP t x)
-    in pure $ mkNode opts (Val b) (msg0 <> "(" <> t <> ") " <> showL opts b <> showVerbose opts " | " x) []
+    pp <- eval (Proxy @p) opts x
+    pure $ case getValueLR NoInline opts msg0 pp [] of
+      Left e -> e
+      Right p ->
+        let b = itoList p
+        in mkNode opts (Val b) (msg0 <> "(" <> t <> ") " <> showL opts b <> showVerbose opts " | " x) [hh pp]
 
 -- | similar to 'Control.Lens.itoList'
 --
@@ -178,7 +187,7 @@ -- Val [(0,'a'),(1,'b'),(2,'c')]
 --
 data IToList (t :: Type) deriving Show
-type IToListT (t :: Type) = IToList' (Hole t)
+type IToListT (t :: Type) = IToList' (Hole t) Id
 
 instance P (IToListT t) x => P (IToList t) x where
   type PP (IToList t) x = PP (IToListT t) x
@@ -261,7 +270,7 @@ -- >>> pz @Concat ["abc","D","eF","","G"]
 -- Val "abcDeFG"
 --
--- >>> pz @(Lift Concat Snd) ('x',["abc","D","eF","","G"])
+-- >>> pz @(Snd >> Concat) ('x',["abc","D","eF","","G"])
 -- Val "abcDeFG"
 --
 data Concat deriving Show
@@ -286,15 +295,17 @@   eval _ = eval (Proxy @(ConcatMapT p q))
 
 
--- | similar to 'cycle' but for a fixed number @n@
+-- | similar to 'cycle' but for a fixed number @n@: for an empty list it just returns an empty list
 --
 -- >>> pz @(Cycle 5 Id) [1,2]
 -- Val [1,2,1,2,1]
 --
+-- >>> pz @(Cycle 5 Id) []
+-- Val []
+--
 data Cycle n p deriving Show
 
 instance ( Show a
-         , Show (t a)
          , PP p x ~ t a
          , P p x
          , Integral (PP n x)
@@ -311,10 +322,10 @@         let hhs = [hh nn, hh pp]
         in case chkSize opts msg0 p hhs of
             Left e ->  e
-            Right _ ->
+            Right ps ->
               let msg1 = msg0 <> "(" <> show n <> ")"
-                  d = take n (Safe.cycleNote msg0 (toList p))
-              in mkNode opts (Val d) (show3 opts msg1 d p) hhs
+                  d = take n (cycle' ps)
+              in mkNode opts (Val d) (show3 opts msg1 d ps) hhs
 
 
 -- | similar to 'toList'
@@ -356,6 +367,7 @@         z = toList as
     in pure $ mkNode opts (Val z) (msg0 <> showVerbose opts " " as) []
 
+-- | explicit version of 'Null' with an extra parameter @p@ to point to the value
 data Null' p deriving Show
 
 instance ( Show (t a)
src/Predicate/Data/IO.hs view
@@ -323,6 +323,7 @@ 
 -- | read in a value of a given type from stdin with a prompt: similar to 'System.IO.readIO'
 type ReadIO (t :: Type) = ReadIO' t "Enter value"
+-- | similar to 'ReadIO' but allow the user to specify the prompt string @s@
 type ReadIO' (t :: Type) s = Stdout (s <> ":") >> Stdin >> ReadP t Id
 -- eg pa @(ReadIO Int + ReadIO Int) ()
 
src/Predicate/Data/Lifted.hs view
@@ -658,6 +658,9 @@   type PP (K p q) a = PP p a
   eval _ = eval (Proxy @(MsgI "K " p))
 
+-- useful only when you need an extra arg function or p is a constant or p and Id can be the same
+-- also useful if you dont want to have parens cos of >>
+-- Lift Rescan Fst wont work as Id and Fst are different: how can regex pattern be the same as the value you are matching against!
 -- | Lift a no arg Adt to a function of one argument (for use with 'Dot' and 'RDot')
 --
 -- >>> pl @(Lift Len Snd) (True,"abcdef")
@@ -989,7 +992,7 @@ -- >>> pz @((1 ... 10) >>= EmptyBool [] Even '[Id,Id]) ()
 -- Val [[2,2],[4,4],[6,6],[8,8],[10,10]]
 --
--- >>> pz @( (1 ... 10) >>= If Even '[Id,Id] (EmptyT [])) ()
+-- >>> pz @((1 ... 10) >>= If Even '[Id,Id] (EmptyT [])) ()
 -- Val [2,2,4,4,6,6,8,8,10,10]
 --
 -- >>> pz @(Lookup 0 Id >>= Lookup 1 Id) [[1,2,3]]
@@ -1068,10 +1071,10 @@ -- >>> pz @(Flip Map' Id Succ) [1..5]
 -- Val [2,3,4,5,6]
 --
--- >>> pz @( Flip '(,) 'True 2) ()
+-- >>> pz @(Flip '(,) 'True 2) ()
 -- Val (2,True)
 --
--- >>> pz @( Flip ('(,,) 1) 2 Id) "ab"
+-- >>> pz @(Flip ('(,,) 1) 2 Id) "ab"
 -- Val (1,"ab",2)
 --
 data Flip (p :: k1 -> k2 -> k3) (q :: k2) (r :: k1) deriving Show
src/Predicate/Data/List.hs view
@@ -66,6 +66,9 @@   , Break
   , Span
   , Intercalate
+  , PartitionsBy
+  , IMap
+  , IList
 
  -- ** miscellaneous
   , Elem
@@ -100,8 +103,9 @@ import Predicate.Core
 import Predicate.Misc
 import Predicate.Util
-import Predicate.Data.Ordering (type (==), OrdA', type (>))
-import Predicate.Data.Numeric (Mod)
+import Predicate.Data.Ordering (type (==), Comparing, type (>))
+import Predicate.Data.Numeric (Mod, type (-))
+import Predicate.Data.Enum (type (...))
 import Predicate.Data.Monoid (type (<>))
 import Control.Lens
 import Data.List (foldl', partition, intercalate, inits, tails, unfoldr, sortOn)
@@ -175,7 +179,7 @@ -- >>> pz @(123 :+ EmptyList _) "somestuff"
 -- Val [123]
 --
--- >>> pl @(FlipT (:+) Fst Snd) ([1..5],99)
+-- >>> pl @(Flip (:+) Fst Snd) ([1..5],99)
 -- Present [99,1,2,3,4,5] ((:+) [99,1,2,3,4,5] | p=99 | q=[1,2,3,4,5])
 -- Val [99,1,2,3,4,5]
 --
@@ -191,7 +195,7 @@ -- Present [4,1,2,3] ((:+) [4,1,2,3] | p=4 | q=[1,2,3])
 -- Val [4,1,2,3]
 --
--- >>> pl @(FlipT (:+) '[1,2,3] 5) ()
+-- >>> pl @(Flip (:+) '[1,2,3] 5) ()
 -- Present [5,1,2,3] ((:+) [5,1,2,3] | p=5 | q=[1,2,3])
 -- Val [5,1,2,3]
 --
@@ -1415,11 +1419,11 @@ -- >>> pz @(SortBy ((L11 ==! L21) <> (L22 ==! L12)) Id) [(10,"ab"),(4,"x"),(20,"bbb"),(4,"a"),(4,"y")]
 -- Val [(4,"y"),(4,"x"),(4,"a"),(10,"ab"),(20,"bbb")]
 --
--- >>> pl @(SortBy (Swap >> OrdA' Fst Fst) Snd) ((),[('z',1),('a',10),('m',22)])
+-- >>> pl @(SortBy (Swap >> Comparing Fst) Snd) ((),[('z',1),('a',10),('m',22)])
 -- Present [('z',1),('m',22),('a',10)] (SortBy [('z',1),('m',22),('a',10)])
 -- Val [('z',1),('m',22),('a',10)]
 --
--- >>> pl @(SortBy (OrdA' Reverse Reverse) Id) ["az","by","cx","aa"]
+-- >>> pl @(SortBy (Comparing Reverse) Id) ["az","by","cx","aa"]
 -- Present ["aa","cx","by","az"] (SortBy ["aa","cx","by","az"])
 -- Val ["aa","cx","by","az"]
 --
@@ -1427,7 +1431,7 @@ -- Error pivot=5 value=3(2) (Partition(i=1, a=(5,3)) excnt=2 | SortBy)
 -- Fail "pivot=5 value=3(2)"
 --
--- >>> pl @(SortBy (If (Fst==50 && Snd==3) (FailT _ (PrintT "pivot=%d value=%d" Id)) OrdA) Snd) ((), [5,7,3,1,6,2,1,3])
+-- >>> pl @(SortBy (If (Fst==50 && Snd==3) (FailT _ (PrintT "pivot=%d value=%d" Id)) Compare) Snd) ((), [5,7,3,1,6,2,1,3])
 -- Present [1,1,2,3,3,5,6,7] (SortBy [1,1,2,3,3,5,6,7])
 -- Val [1,1,2,3,3,5,6,7]
 --
@@ -1511,7 +1515,7 @@ -- Val [('a',9),('a',10),('m',10),('m',22),('z',1)]
 --
 data SortOn p q deriving Show
-type SortOnT p q = SortBy (OrdA' p p) q
+type SortOnT p q = SortBy (Comparing p) q
 
 instance P (SortOnT p q) x => P (SortOn p q) x where
   type PP (SortOn p q) x = PP (SortOnT p q) x
@@ -1528,7 +1532,7 @@ -- Val [('z',1),('m',22),('a',10)]
 --
 data SortOnDesc p q deriving Show
-type SortOnDescT p q = SortBy (Swap >> OrdA' p p) q
+type SortOnDescT p q = SortBy (Swap >> Comparing p) q
 
 instance P (SortOnDescT p q) x => P (SortOnDesc p q) x where
   type PP (SortOnDesc p q) x = PP (SortOnDescT p q) x
@@ -1606,6 +1610,7 @@       Left e -> e
       Right p -> mkNode opts (Val [p]) msg0 [hh pp]
 
+-- | creates an empty list for the given pointer to a type @t@
 data EmptyList' t deriving Show
 
 instance P (EmptyList' t) x where
@@ -2142,3 +2147,70 @@           Right _ ->
             let d = liftA2 (,) p q
             in mkNode opts (Val d) (show3' opts msg0 d "p=" p <> showVerbose opts " | q=" q) hhs
+
+-- | experimental: sorts then partitions and then sorts each partitions based on the leftmost occurring value in the original list
+--   if the existing order of data is fine then use 'Predicate.Data.List.GroupBy' as you do not need this
+--
+-- >>> pz @(PartitionsBy (Fst ==! Snd) (L11 == L21) Id) [10,9,9,1,9]
+-- Val [[10],[9,9,9],[1]]
+--
+-- >>> pz @(PartitionsBy Compare (L11 < L21) Id) "efaffabec"
+-- Val ["a","f","f","abce","ef"]
+--
+-- >>> pz @(PartitionsBy 'GT 'True Id) "efaffabec"
+-- Val ["cebaffafe"]
+--
+-- >>> pz @(PartitionsBy 'GT 'False Id) "efaffabec"
+-- Val ["e","f","a","f","f","a","b","e","c"]
+--
+-- >>> pz @(PartitionsBy (Fst ==! Snd) (L12 > L22) Id) [10,9,9,1,9,4]
+-- Val [[9],[1],[9,10],[4,9]]
+--
+-- >>> pz @(PartitionsBy (L11 ==! L21) (L12 > L22) Id) "eddadc"
+-- Val ["d","a","de","cd"]
+--
+-- >>> pz @(PartitionsBy (L11 ==! L21) (L11 < L21) Id) [10,9,9,1,9,4]
+-- Val [[9],[1,4,9],[9,10]]
+--
+data PartitionsBy p q r deriving Show
+type PartitionsByT p q r = SortBy p (Zip r (0 ... (Length r - 1))) >> GroupBy q Id >> SortOn (Head >> Snd) Id >> Map (Map Fst)
+
+instance P (PartitionsByT p q r) x => P (PartitionsBy p q r) x where
+  type PP (PartitionsBy p q r) x = PP (PartitionsByT p q r) x
+  eval _ = eval (Proxy @(PartitionsByT p q r))
+
+-- | add an index to map
+--
+-- >>> pz @(IMap (Second Succ) Id) "hello"
+-- Val [(0,'i'),(1,'f'),(2,'m'),(3,'m'),(4,'p')]
+--
+-- >>> pz @(IMap (10 ^ Fst * Snd) Id >> Sum) [3,2,7,9]
+-- Val 9723
+--
+-- >>> pz @(IMap (2 ^ Fst * Snd) Id) [1,1,1,0,1,0,1]
+-- Val [1,2,4,0,16,0,64]
+--
+-- >>> pz @(Rescan "^(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)$" >> Map (Snd >> IMap (GuardBool (PrintT "bad value=%d %s" Id) (Snd >> ReadP Int Id < 255)) Id)) "123.222.999.3"
+-- Fail "bad value=2 999"
+--
+-- >>> pz @(Rescan "^(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)$" >> Map (Snd >> IMap (GuardBool (PrintT "bad value=%d %s" Id) (Snd >> ReadP Int Id < 255)) Id)) "123.222.99.3"
+-- Val [[True,True,True,True]]
+--
+data IMap p q deriving Show
+type IMapT p q = ZipWith p (0 ... (Length q - 1)) q
+
+instance P (IMapT p q) x => P (IMap p q) x where
+  type PP (IMap p q) x = PP (IMapT p q) x
+  eval _ = eval (Proxy @(IMapT p q))
+
+-- | add an index to list
+--
+-- >>> pz @IList "abcdef"
+-- Val [(0,'a'),(1,'b'),(2,'c'),(3,'d'),(4,'e'),(5,'f')]
+--
+data IList deriving Show
+type IListT = Zip (0 ... (Len - 1)) Id
+
+instance P IListT x => P IList x where
+  type PP IList x = PP IListT x
+  eval _ = eval (Proxy @IListT)
src/Predicate/Data/Numeric.hs view
@@ -92,22 +92,22 @@ -- >>> import Data.Time
 
 -- | 'fromInteger' function where you need to provide a reference to the type @t@ of the result
-data FromInteger' t n deriving Show
+data FromInteger' t p deriving Show
 
 instance ( Num (PP t a)
-         , Integral (PP n a)
-         , P n a
+         , Integral (PP p a)
+         , P p a
          , Show (PP t a)
-         ) => P (FromInteger' t n) a where
-  type PP (FromInteger' t n) a = PP t a
+         ) => P (FromInteger' t p) a where
+  type PP (FromInteger' t p) a = PP t a
   eval _ opts a = do
     let msg0 = "FromInteger"
-    nn <- eval (Proxy @n) opts a
-    pure $ case getValueLR NoInline opts msg0 nn [] of
+    pp <- eval (Proxy @p) opts a
+    pure $ case getValueLR NoInline opts msg0 pp [] of
       Left e -> e
-      Right n ->
-        let b = fromInteger (fromIntegral n)
-        in mkNode opts (Val b) (msg0 <> " " <> showL opts b) [hh nn]
+      Right p ->
+        let b = fromInteger (fromIntegral p)
+        in mkNode opts (Val b) (msg0 <> " " <> showL opts b) [hh pp]
 
 -- | 'fromInteger' function where you need to provide the type @t@ of the result
 --
@@ -138,30 +138,30 @@ --
 data FromInteger (t :: Type) deriving Show
 type FromIntegerT (t :: Type) = FromInteger' (Hole t) Id
---type FromIntegerP n = FromInteger' UnproxyT n
+--type FromIntegerP p = FromInteger' UnproxyT n
 
 instance P (FromIntegerT t) x => P (FromInteger t) x where
   type PP (FromInteger t) x = PP (FromIntegerT t) x
   eval _ = eval (Proxy @(FromIntegerT t))
 
 -- | 'fromIntegral' function where you need to provide a reference to the type @t@ of the result
-data FromIntegral' t n deriving Show
+data FromIntegral' t p deriving Show
 
 instance ( Num (PP t a)
-         , Integral (PP n a)
-         , P n a
+         , Integral (PP p a)
+         , P p a
          , Show (PP t a)
-         , Show (PP n a)
-         ) => P (FromIntegral' t n) a where
-  type PP (FromIntegral' t n) a = PP t a
+         , Show (PP p a)
+         ) => P (FromIntegral' t p) a where
+  type PP (FromIntegral' t p) a = PP t a
   eval _ opts a = do
     let msg0 = "FromIntegral"
-    nn <- eval (Proxy @n) opts a
-    pure $ case getValueLR NoInline opts msg0 nn [] of
+    pp <- eval (Proxy @p) opts a
+    pure $ case getValueLR NoInline opts msg0 pp [] of
       Left e -> e
-      Right n ->
-        let b = fromIntegral n
-        in mkNode opts (Val b) (show3 opts msg0 b n) [hh nn]
+      Right p ->
+        let b = fromIntegral p
+        in mkNode opts (Val b) (show3 opts msg0 b p) [hh pp]
 
 -- | 'fromIntegral' function where you need to provide the type @t@ of the result
 --
src/Predicate/Data/Ordering.hs view
@@ -35,11 +35,9 @@   , Lt
   , Ne
   , type (==!)
-  , OrdA'
-  , OrdA
+  , Comparing
+  , Compare
   , type (===~)
-  , Cmp
-  , CmpI
   , Asc
   , Asc'
   , Desc
@@ -103,6 +101,15 @@   eval _ = eval (Proxy @(LeT n))
 
 -- | compare if expression @p@ is less than to @q@
+--
+-- >>> pl @(Lt 4) 123
+-- False (123 < 4)
+-- Val False
+--
+-- >>> pl @(Lt 4) 1
+-- True (1 < 4)
+-- Val True
+--
 data Lt n deriving Show
 type LtT n = Id < n
 
@@ -243,6 +250,19 @@   eval _ = evalBool (Proxy @(CmpI 'CGe p q))
 
 -- | case-insensitive compare if string expression @p@ is equal to @q@
+--
+-- >>> pl @("Abc" ==~ Id) "abc"
+-- True (Abc ==~ abc)
+-- Val True
+--
+-- >>> pl @(Fst ==~ Snd) ("aBc","AbC")
+-- True (aBc ==~ AbC)
+-- Val True
+--
+-- >>> pl @(Fst ==~ Snd && Fst == Snd) ("Abc","Abc")
+-- True (True && True)
+-- Val True
+--
 data p ==~ q deriving Show
 infix 4 ==~
 
@@ -336,19 +356,33 @@         let d = compare p q
         in mkNode opts (Val d) (msg0 <> " " <> showL opts p <> " " <> prettyOrd d <> " " <> showL opts q) [hh pp, hh qq]
 
--- | similar to 'compare' but using a tuple as input
-data OrdA deriving Show
+-- | similar to 'compare' for a tuple
+--
+-- >>> pl @Compare ('b','A')
+-- Present GT ((==!) 'b' > 'A')
+-- Val GT
+--
+-- >>> pl @(Compare) (13,99)
+-- Present LT ((==!) 13 < 99)
+-- Val LT
+--
+data Compare deriving Show
 
-instance P (OrdA' Id Id) x => P OrdA x where
-  type PP OrdA x = PP (OrdA' Id Id) x
-  eval _ = eval (Proxy @(OrdA' Id Id))
+instance P (Comparing Id) x => P Compare x where
+  type PP Compare x = PP (Comparing Id) x
+  eval _ = eval (Proxy @(Comparing Id))
 
-data OrdA' p q deriving Show
-type OrdAT' p q = (Fst >> p) ==! (Snd >> q)
+-- | similar to 'Data.Ord.comparing' for a tuple
+--
+-- >>> pz @(Comparing Len) ("abc","123456")
+-- Val LT
+--
+data Comparing p deriving Show
+type ComparingT p = (Fst >> p) ==! (Snd >> p)
 
-instance P (OrdAT' p q) x => P (OrdA' p q) x where
-  type PP (OrdA' p q) x = PP (OrdAT' p q) x
-  eval _ = eval (Proxy @(OrdAT' p q))
+instance P (ComparingT p) x => P (Comparing p) x where
+  type PP (Comparing p) x = PP (ComparingT p) x
+  eval _ = eval (Proxy @(ComparingT p))
 
 -- | compare two strings ignoring case and return an ordering
 --
@@ -371,19 +405,6 @@ -- Present EQ ((===~) Abc = abc)
 -- Val EQ
 --
---
--- >>> pl @("Abc" ==~ Id) "abc"
--- True (Abc ==~ abc)
--- Val True
---
--- >>> pl @(Fst ==~ Snd) ("aBc","AbC")
--- True (aBc ==~ AbC)
--- Val True
---
--- >>> pl @(Fst ==~ Snd && Fst == Snd) ("Abc","Abc")
--- True (True && True)
--- Val True
---
 data p ===~ q deriving Show
 infix 4 ===~
 
@@ -403,23 +424,6 @@         in mkNode opts (Val d) (msg0 <> " " <> p <> " " <> prettyOrd d <> " " <> q) [hh pp, hh qq]
 
 -- | compare two values using the given ordering @o@
---
--- >>> pl @(Lt 4) 123
--- False (123 < 4)
--- Val False
---
--- >>> pl @(Lt 4) 1
--- True (1 < 4)
--- Val True
---
--- >>> pl @(Negate 7 <..> 20) (-4)
--- True (-7 <= -4 <= 20)
--- Val True
---
--- >>> pl @(Negate 7 <..> 20) 21
--- False (21 <= 20)
--- Val False
---
 data Cmp (o :: OrderingP) p q deriving Show
 
 instance ( GetOrd o
src/Predicate/Data/Proxy.hs view
@@ -38,6 +38,7 @@ import qualified GHC.TypeLits as GL
 import Data.Kind (Type)
 import Data.Typeable (Proxy(..))
+import Control.Lens
 -- $setup
 -- >>> :set -XDataKinds
 -- >>> :set -XTypeApplications
@@ -195,7 +196,7 @@         zz <- eval (Proxy @z) opts q
         pure $ case getValueLR NoInline opts msg0 zz [hh qq] of
           Left e -> e
-          Right _z -> mkNodeCopy opts zz (msg0 <> nullIf " | " (_ttString zz)) [hh qq,hh zz]
+          Right _z -> mkNodeCopy opts zz (msg0 <> nullIf " | " (zz ^. ttString)) [hh qq,hh zz]
 
 -- the key is to pass all the vars into the type family so ghc can figure stuff out
 type family Pop0T (p :: Type) (q :: Type) :: Type where
@@ -238,6 +239,7 @@ --
 -- >>> pz @(Pop1 (Proxy ('(,) 'True)) Len "abc") ()
 -- Val (True,3)
+--
 data Pop1 p q r deriving Show
 
 instance ( P r x
@@ -255,7 +257,7 @@         zz <- eval (Proxy @(z q)) opts r
         pure $ case getValueLR NoInline opts msg0 zz [hh rr] of
           Left e -> e
-          Right _z -> mkNodeCopy opts zz (msg0 <> nullIf " | " (_ttString zz)) [hh rr,hh zz]
+          Right _z -> mkNodeCopy opts zz (msg0 <> nullIf " | " (zz ^. ttString)) [hh rr,hh zz]
 
 type family Pop1T (p :: Type) (q :: k) (r :: Type) :: Type where
   Pop1T (Proxy z) q r = PP (z q) r
@@ -317,7 +319,7 @@         zz <- eval (Proxy @(z w)) opts r
         pure $ case getValueLR NoInline opts msg0 zz [hh rr] of
           Left e -> e
-          Right _z -> mkNodeCopy opts zz (msg0 <> nullIf " | " (_ttString zz)) [hh rr,hh zz]
+          Right _z -> mkNodeCopy opts zz (msg0 <> nullIf " | " (zz ^. ttString)) [hh rr,hh zz]
 
 type family Pop1'T (p :: Type) (q :: Type) (r :: Type) :: Type where
   Pop1'T (Proxy z) (Proxy w) r = PP (z w) r
@@ -354,7 +356,7 @@         zz <- eval (Proxy @(z q r)) opts s
         pure $ case getValueLR NoInline opts msg0 zz [hh ss] of
           Left e -> e
-          Right _z -> mkNodeCopy opts zz (msg0 <> nullIf " | " (_ttString zz)) [hh ss,hh zz]
+          Right _z -> mkNodeCopy opts zz (msg0 <> nullIf " | " (zz ^. ttString)) [hh ss,hh zz]
 
 -- pass all the arguments in!!! else ghc gets confused
 type family Pop2T (p :: Type) (q :: k) (r :: k1) (s :: Type) :: Type where
@@ -398,7 +400,7 @@         zz <- eval (Proxy @(z w v)) opts s
         pure $ case getValueLR NoInline opts msg0 zz [hh ss] of
           Left e -> e
-          Right _z -> mkNodeCopy opts zz (msg0 <> nullIf " | " (_ttString zz)) [hh ss,hh zz]
+          Right _z -> mkNodeCopy opts zz (msg0 <> nullIf " | " (zz ^. ttString)) [hh ss,hh zz]
 
 -- pass in all the arguments otherwise ghc gets confused
 type family Pop2'T (p :: Type) (q :: Type) (r :: Type) (s :: Type) :: Type where
src/Predicate/Data/ReadShow.hs view
@@ -133,6 +133,7 @@   type PP (ReadP t p) x = PP (ReadPT t p) x
   eval _ = eval (Proxy @(ReadPT t p))
 
+-- | same as 'ReadMaybe' except @t@ is a pointer to the type
 data ReadMaybe' t p deriving Show
 
 instance ( P p x
src/Predicate/Data/Regex.hs view
@@ -175,6 +175,12 @@ -- >>> pz @(Rescan' '[] Snd "13:05:25") ('a',"^(\\d{2}):(\\d{2}):(\\d{2})$")
 -- Val [("13:05:25",["13","05","25"])]
 --
+-- >>> pz @('(Id,Intercalate '["\\."] (Repeat 4 "([01]?\\d?\\d|2[0-4]\\d|25[0-5])") >> Concat) >> Rescan' '[] ("^" <> Snd <> "$") Fst) "1.2.3.255" -- have to use Rescan' here: Lift helps not!
+-- Val [("1.2.3.255",["1","2","3","255"])]
+--
+-- >>> pz @('(Id,Intercalate '["\\."] (Repeat 4 "([01]?\\d?\\d|2[0-4]\\d|25[0-5])") >> Concat) >> Rescan' '[] ("^" <> Snd <> "$") Fst >> FMap (Second (FMap (ReadP Int Id)))) "1.2.3.255"
+-- Val [("1.2.3.255",[1,2,3,255])]
+--
 data Rescan' (rs :: [ROpt]) p q deriving Show
 
 instance ( GetROpts rs
@@ -258,6 +264,9 @@ -- Present [("fe",["fe"]),("b1",["b1"]),("2a",["2a"])] (Rescan (([[:xdigit:]]{2})) [("fe",["fe"]),("b1",["b1"]),("2a",["2a"])] | wfeb12az)
 -- Val [("fe",["fe"]),("b1",["b1"]),("2a",["2a"])]
 --
+-- >>> pz @(Rescan "^Date\\((\\d+)(\\d{3}[+-]\\d{4})\\)" >> Head >> Snd >> (Id !! 0 <> "." <> Id !! 1)  >> ParseTimeP ZonedTime "%s%Q%z") "Date(1593460089052+0800)"
+-- Val 2020-06-30 03:48:09.052 +0800
+--
 data Rescan p deriving Show
 type RescanT p = Rescan' '[] p Id
 
@@ -265,7 +274,7 @@   type PP (Rescan p) x = PP (RescanT p) x
   eval _ = eval (Proxy @(RescanT p))
 
-
+-- | similar to 'RescanRanges' but also allows the regex options @rs@ to be specified
 data RescanRanges' (rs :: [ROpt]) p q deriving Show
 
 instance ( GetROpts rs
@@ -369,11 +378,6 @@   type PP (Resplit p) x = PP (ResplitT p) x
   eval _ = eval (Proxy @(ResplitT p))
 
--- | replaces regex @s@ with a string @s1@ inside the value: see 'RH.sub' and 'RH.gsub'
---
--- >>> pz @(ReplaceAllString 'ROverWrite "\\." ":" Id) "141.201.1.22"
--- Val "141:201:1:22"
---
 data ReplaceImpl (alle :: Bool) (rs :: [ROpt]) p q r deriving Show
 
 instance ( GetBool b
@@ -416,6 +420,7 @@                            RReplace3 s -> (if alle then RH.gsub else RH.sub) regex s r
                in mkNode opts (Val ret) (msg1 <> " " <> litL opts r <> litVerbose opts " | " ret) (hhs <> [hh rr])
 
+-- | replaces all values using regex @p@ with a replacement function @q@ inside the value @r@ using regex options @rs@
 data ReplaceAll' (rs :: [ROpt]) p q r deriving Show
 type ReplaceAllT' (rs :: [ROpt]) p q r = ReplaceImpl 'True rs p q r
 
@@ -423,6 +428,7 @@   type PP (ReplaceAll' rs p q r) x = PP (ReplaceAllT' rs p q r) x
   eval _ = eval (Proxy @(ReplaceAllT' rs p q r))
 
+-- | replaces all values using regex @p@ with a replacement function @q@ inside the value @r@
 data ReplaceAll p q r deriving Show
 type ReplaceAllT p q r = ReplaceAll' '[] p q r
 
@@ -430,6 +436,7 @@   type PP (ReplaceAll p q r) x = PP (ReplaceAllT p q r) x
   eval _ = eval (Proxy @(ReplaceAllT p q r))
 
+-- | replaces the first value using regex @p@ with a replacement function @q@ inside the value @r@ using regex options @rs@
 data ReplaceOne' (rs :: [ROpt]) p q r deriving Show
 type ReplaceOneT' (rs :: [ROpt]) p q r = ReplaceImpl 'False rs p q r
 
@@ -437,21 +444,7 @@   type PP (ReplaceOne' rs p q r) x = PP (ReplaceOneT' rs p q r) x
   eval _ = eval (Proxy @(ReplaceOneT' rs p q r))
 
--- | replace first occurrence of string @p@ with @q@ in @r@
---
--- >>> pl @(ReplaceOneString 'ROverWrite "abc" "def" Id) "123abc456abc"
--- Present "123def456abc" (ReplaceOne (abc) 123abc456abc | 123def456abc)
--- Val "123def456abc"
---
--- >>> pz @(Rescan "^Date\\((\\d+[+-]\\d{4})\\)" >> Head >> Snd >> Id !! 0 >> ReplaceOneString 'RPrepend "\\d{3}[+-]" "." Id >> ParseTimeP ZonedTime "%s%Q%z") "Date(1530144000123+0530)"
--- Val 2018-06-28 05:30:00.123 +0530
---
--- >>> pz @(Rescan "^Date\\((\\d+[+-]\\d{4})\\)" >> Head >> Snd >> Id !! 0 >> ReplaceOneString 'RPrepend "\\d{3}[+-]" "." Id >> ParseTimeP ZonedTime "%s%Q%z") "Date(1593460089052+0800)"
--- Val 2020-06-30 03:48:09.052 +0800
---
--- >>> pz @(Rescan "^Date\\((\\d+)(\\d{3}[+-]\\d{4})\\)" >> Head >> Snd >> (Id !! 0 <> "." <> Id !! 1)  >> ParseTimeP ZonedTime "%s%Q%z") "Date(1593460089052+0800)"
--- Val 2020-06-30 03:48:09.052 +0800
---
+-- | replaces first value using regex @p@ with a replacement function @q@ inside the value @r@
 data ReplaceOne p q r deriving Show
 type ReplaceOneT p q r = ReplaceOne' '[] p q r
 
@@ -459,6 +452,14 @@   type PP (ReplaceOne p q r) x = PP (ReplaceOneT p q r) x
   eval _ = eval (Proxy @(ReplaceOneT p q r))
 
+-- | replace all occurrences of string @p@ with @q@ in @r@ using regex options @rs@
+data ReplaceAllString' (rs :: [ROpt]) (o :: ReplaceFnSub) p q r deriving Show
+type ReplaceAllStringT' (rs :: [ROpt]) (o :: ReplaceFnSub) p q r = ReplaceAll' rs p (ReplaceFn o q) r
+
+instance P (ReplaceAllStringT' rs o p q r) x => P (ReplaceAllString' rs o p q r) x where
+  type PP (ReplaceAllString' rs o p q r) x = PP (ReplaceAllStringT' rs o p q r) x
+  eval _ = eval (Proxy @(ReplaceAllStringT' rs o p q r))
+
 -- | replace all occurrences of string @p@ with @q@ in @r@
 --
 -- >>> pl @(ReplaceAllString 'ROverWrite "abc" "def" Id) "123abc456abc"
@@ -485,13 +486,9 @@ -- Present "123AbC456abcdef" (ReplaceAll (abc) 123AbC456abc | 123AbC456abcdef)
 -- Val "123AbC456abcdef"
 --
-data ReplaceAllString' (rs :: [ROpt]) (o :: ReplaceFnSub) p q r deriving Show
-type ReplaceAllStringT' (rs :: [ROpt]) (o :: ReplaceFnSub) p q r = ReplaceAll' rs p (ReplaceFn o q) r
-
-instance P (ReplaceAllStringT' rs o p q r) x => P (ReplaceAllString' rs o p q r) x where
-  type PP (ReplaceAllString' rs o p q r) x = PP (ReplaceAllStringT' rs o p q r) x
-  eval _ = eval (Proxy @(ReplaceAllStringT' rs o p q r))
-
+-- >>> pz @(ReplaceAllString 'ROverWrite "\\." ":" Id) "141.201.1.22"
+-- Val "141:201:1:22"
+--
 data ReplaceAllString o p q r deriving Show
 type ReplaceAllStringT o p q r = ReplaceAllString' '[] o p q r
 
@@ -499,6 +496,7 @@   type PP (ReplaceAllString o p q r) x = PP (ReplaceAllStringT o p q r) x
   eval _ = eval (Proxy @(ReplaceAllStringT o p q r))
 
+-- | same as 'ReplaceOneString' but allow setting regex options with @rs@
 data ReplaceOneString' (rs :: [ROpt]) (o :: ReplaceFnSub) p q r deriving Show
 type ReplaceOneStringT' (rs :: [ROpt]) (o :: ReplaceFnSub) p q r = ReplaceOne' rs p (ReplaceFn o q) r
 
@@ -506,6 +504,18 @@   type PP (ReplaceOneString' rs o p q r) x = PP (ReplaceOneStringT' rs o p q r) x
   eval _ = eval (Proxy @(ReplaceOneStringT' rs o p q r))
 
+-- | replace first occurrence of string @p@ with @q@ in @r@
+--
+-- >>> pl @(ReplaceOneString 'ROverWrite "abc" "def" Id) "123abc456abc"
+-- Present "123def456abc" (ReplaceOne (abc) 123abc456abc | 123def456abc)
+-- Val "123def456abc"
+--
+-- >>> pz @(Rescan "^Date\\((\\d+[+-]\\d{4})\\)" >> Head >> Snd >> Id !! 0 >> ReplaceOneString 'RPrepend "\\d{3}[+-]" "." Id >> ParseTimeP ZonedTime "%s%Q%z") "Date(1530144000123+0530)"
+-- Val 2018-06-28 05:30:00.123 +0530
+--
+-- >>> pz @(Rescan "^Date\\((\\d+[+-]\\d{4})\\)" >> Head >> Snd >> Id !! 0 >> ReplaceOneString 'RPrepend "\\d{3}[+-]" "." Id >> ParseTimeP ZonedTime "%s%Q%z") "Date(1593460089052+0800)"
+-- Val 2020-06-30 03:48:09.052 +0800
+--
 data ReplaceOneString (o :: ReplaceFnSub) p q r deriving Show
 type ReplaceOneStringT (o :: ReplaceFnSub) p q r = ReplaceOneString' '[] o p q r
 
src/Predicate/Data/String.hs view
@@ -79,7 +79,7 @@         b =  (fl . fr) p
      in pure $ mkNode opts (Val (b ^. DTL.packed)) (msg0 <> litL opts b <> litVerbose opts " | " p) []
 
--- | similar to 'T.stripStart'
+-- | similar to 'Data.Text.stripStart'
 --
 -- >>> pz @(Snd >> TrimL) (20," abc   ")
 -- Val "abc   "
@@ -91,7 +91,7 @@   type PP TrimL x = PP TrimLT x
   eval _ = eval (Proxy @TrimLT)
 
--- | similar to 'T.stripEnd'
+-- | similar to 'Data.Text.stripEnd'
 --
 -- >>> pz @(Snd >> TrimR) (20," abc   ")
 -- Val " abc"
@@ -109,7 +109,7 @@   type PP TrimR x = PP TrimRT x
   eval _ = eval (Proxy @TrimRT)
 
--- | similar to 'T.strip'
+-- | similar to 'Data.Text.strip'
 --
 -- >>> pz @(Snd >> TrimBoth) (20," abc   ")
 -- Val "abc"
@@ -154,7 +154,7 @@                   in if after == p then Just before else Nothing
         in mkNode opts (Val (fmap (view DTL.packed) b)) (msg0 <> showL opts b <> litVerbose opts " | p=" p <> litVerbose opts " | q=" q) [hh pp, hh qq]
 
--- | similar to 'T.stripLeft'
+-- | similar to 'Data.Text.stripLeft'
 --
 -- >>> pz @(StripL "xyz" Id) "xyzHello"
 -- Val (Just "Hello")
@@ -172,7 +172,7 @@   type PP (StripL p q) x = PP (StripLT p q) x
   eval _ = eval (Proxy @(StripLT p q))
 
--- | similar to 'T.stripRight'
+-- | similar to 'Data.Text.stripRight'
 --
 -- >>> pz @(StripR "xyz" Id) "Hello xyz"
 -- Val (Just "Hello ")
@@ -215,7 +215,7 @@         let msg1 = msg0 <> (if ignore then "I" else "") <> " | " <> p
         in mkNodeB opts (on ff lwr p q) (msg1 <> " " <> litL opts q) [hh pp, hh qq]
 
--- | similar to 'isPrefixOf' for strings
+-- | similar to 'Data.List.isPrefixOf' for strings
 --
 -- >>> pl @(IsPrefixC "xy" Id) "xyzabw"
 -- True (IsPrefixC | xy xyzabw)
@@ -235,7 +235,7 @@   type PP (IsPrefixC p q) x = PP (IsPrefixCT p q) x
   eval _ = evalBool (Proxy @(IsPrefixCT p q))
 
--- | similar to 'isInfixOf' for strings
+-- | similar to 'Data.List.isInfixOf' for strings
 --
 -- >>> pl @(IsInfixC "ab" Id) "xyzabw"
 -- True (IsInfixC | ab xyzabw)
@@ -260,7 +260,7 @@   type PP (IsInfixC p q) x = PP (IsInfixCT p q) x
   eval _ = evalBool (Proxy @(IsInfixCT p q))
 
--- | similar to 'isSuffixOf' for strings
+-- | similar to 'Data.List.isSuffixOf' for strings
 --
 -- >>> pl @(IsSuffixC "bw" Id) "xyzabw"
 -- True (IsSuffixC | bw xyzabw)
@@ -280,7 +280,7 @@   type PP (IsSuffixC p q) x = PP (IsSuffixCT p q) x
   eval _ = evalBool (Proxy @(IsSuffixCT p q))
 
--- | similar to case insensitive 'isPrefixOf' for strings
+-- | similar to case insensitive 'Data.List.isPrefixOf' for strings
 --
 -- >>> pz @(IsPrefixCI "abc" "aBcbCd") ()
 -- Val True
@@ -292,7 +292,7 @@   type PP (IsPrefixCI p q) x = PP (IsPrefixCIT p q) x
   eval _ = evalBool (Proxy @(IsPrefixCIT p q))
 
--- | similar to case insensitive 'isInfixOf' for strings
+-- | similar to case insensitive 'Data.List.isInfixOf' for strings
 --
 -- >>> pl @(IsInfixCI "aB" Id) "xyzAbw"
 -- True (IsInfixCI | aB xyzAbw)
@@ -308,7 +308,7 @@   type PP (IsInfixCI p q) x = PP (IsInfixCIT p q) x
   eval _ = evalBool (Proxy @(IsInfixCIT p q))
 
--- | similar to case insensitive 'isSuffixOf' for strings
+-- | similar to case insensitive 'Data.List.isSuffixOf' for strings
 --
 data IsSuffixCI p q deriving Show
 type IsSuffixCIT p q = IsFixImplC 'GT 'True p q
src/Predicate/Data/These.hs view
@@ -71,7 +71,7 @@ -- >>> import Predicate.Prelude
 -- >>> import qualified Data.Semigroup as SG
 
--- | similar to 'partitionThese'. returns a 3-tuple with the results so use 'Fst' 'Snd' 'Thd' to extract
+-- | similar to 'Data.These.partitionThese'. returns a 3-tuple with the results so use 'Fst' 'Snd' 'Thd' to extract
 --
 -- >>> pz @PartitionThese [This 'a', That 2, This 'c', These 'z' 1, That 4, These 'a' 2, That 99]
 -- Val ("ac",[2,4,99],[('z',1),('a',2)])
@@ -95,7 +95,7 @@         b = partitionThese as
     in pure $ mkNode opts (Val b) (show3 opts msg0 b as) []
 
--- | similar to 'TheseC.catThis'
+-- | similar to 'Data.These.Combinators.catThis'
 --
 -- >>> pz @(Thiss) [That 1, This 'a', These 'b' 33, This 'd', That 4]
 -- Val "ad"
@@ -113,7 +113,7 @@   type PP Thiss x = PP ThissT x
   eval _ = eval (Proxy @ThissT)
 
--- | similar to 'TheseC.catThat'
+-- | similar to 'Data.These.Combinators.catThat'
 --
 -- >>> pl @Thats [This 1, This 10,That 'x', This 99, That 'y']
 -- Present "xy" ((>>) "xy" | {Snd "xy" | ([1,10,99],"xy",[])})
@@ -126,7 +126,7 @@   type PP Thats x = PP ThatsT x
   eval _ = eval (Proxy @ThatsT)
 
--- | similar to 'TheseC.catThese'
+-- | similar to 'Data.These.Combinators.catThese'
 --
 -- >>> pz @(ZipThese Id Tail >> Theses) [1..10]
 -- Val [(1,2),(2,3),(3,4),(4,5),(5,6),(6,7),(7,8),(8,9),(9,10)]
@@ -138,7 +138,7 @@   type PP Theses x = PP ThesesT x
   eval _ = eval (Proxy @ThesesT)
 
--- | similar to 'TheseC.catHere'
+-- | similar to 'Data.These.Combinators.catHere'
 --
 -- >>> pz @(ZipThese Id Tail >> Heres) [1..10]
 -- Val [1,2,3,4,5,6,7,8,9,10]
@@ -154,7 +154,7 @@         b = TheseC.catHere as
     in pure $ mkNode opts (Val b) (show3 opts msg0 b as) []
 
--- | similar to 'TheseC.catThere'
+-- | similar to 'Data.These.Combinators.catThere'
 --
 -- >>> pz @(ZipThese Id Tail >> Theres) [1..10]
 -- Val [2,3,4,5,6,7,8,9,10]
@@ -275,6 +275,7 @@   type PP (MkThis t p) x = PP (MkThisT t p) x
   eval _ = eval (Proxy @(MkThisT t p))
 
+-- | similar to 'MkThat' where @t@ references the type
 data MkThat' t p deriving Show
 
 instance ( Show (PP p x)
src/Predicate/Data/Tuple.hs view
@@ -40,6 +40,7 @@  -- ** inductive tuples
   , EachITuple
   , ToITuple
+  , FromITuple
   , ReverseITuple
   , ToITupleList
 
@@ -177,7 +178,7 @@ -- >>> pz @(Pred *** ShowP Id) (13, True)
 -- Val (12,"True")
 --
--- >>> pl @(FlipT (***) Len (Id * 12)) (99,"cdef")
+-- >>> pl @(Flip (***) Len (Id * 12)) (99,"cdef")
 -- Present (1188,4) ((***) (1188,4) | (99,"cdef"))
 -- Val (1188,4)
 --
@@ -378,6 +379,9 @@ 
 -- | similar to 'Data.Function.on': may require kind signatures: Both is a better choice
 --
+-- >>> pz @(On (==!) Len) ("1ss","x2") -- or use Comparing or Both+Compare
+-- Val GT
+--
 -- >>> pz @('(4,2) >> On (**) (FromIntegral _)) ()
 -- Val 16.0
 --
@@ -390,7 +394,6 @@ -- >>> pz @(Both (Id * Id) >> ((Fst + Snd) ** (1 % 2 >> FromRational _))) (3,4) -- equivalent to the above but easier on ghc
 -- Val 5.0
 --
-
 data On (p :: Type -> Type -> k2) q deriving Show
 
 instance ( P q a
@@ -537,6 +540,25 @@   eval _ opts x = do
     let msg0 = "ToITuple"
     pure $ mkNode opts (Val (toITupleC x)) msg0 []
+
+-- | create flat tuples from inductive tuples
+--
+-- >>> pz @FromITuple (2,(3,(True,('y',()))))
+-- Val (2,3,True,'y')
+--
+-- >>> pz @FromITuple ()
+-- Val ()
+--
+-- >>> pz @FromITuple (1,())
+-- Val 1
+--
+data FromITuple deriving Show
+
+instance FromITupleC x => P FromITuple x where
+  type PP FromITuple x = FromITupleP x
+  eval _ opts x = do
+    let msg0 = "FromITuple"
+    pure $ mkNode opts (Val (fromITupleC x)) msg0 []
 
 -- | reverse an inductive tuple
 --
src/Predicate/Examples/Common.hs view
@@ -132,7 +132,7 @@ -- | @op@ type for validating an ip4 address using a predicate
 type Ip4op' = BoolsN (PrintT "octet %d out of range 0-255 found %d" Id) 4 (0 <..> 0xff)
 -- | @op@ type for validating an ip4 address using a guard
-type Ip4op = GuardsN (PrintT "octet %d out of range 0-255 found %d" Id) 4 (0 <..> 0xff) >> 'True
+type Ip4op = GuardsN 4 (PrintT "octet %d out of range 0-255 found %d" Id) (0 <..> 0xff) >> 'True
 
 -- | @fmt@ type for formatting an ip4 address
 type Ip4fmt = PrintL 4 "%03d.%03d.%03d.%03d" Id
src/Predicate/Misc.hs view
@@ -63,6 +63,7 @@ 
  -- ** inductive tuples
   , ToITupleC(..)
+  , FromITupleC(..)
   , ToITupleListC(..)
   , ReverseITupleC(..)
   , TupleC(..)
@@ -121,12 +122,11 @@   , (~>)
   , errorInProgram
   , drawTreeU
-  , asProxyLeft
-  , asProxyRight
   , removeAnsi
   , _Id
   , sum'
   , product'
+  , cycle'
   , cmpOf
   ) where
 import qualified GHC.TypeNats as GN
@@ -316,11 +316,10 @@ -- >>> toITupleC (123,'x')
 -- (123,('x',()))
 --
-
 class ToITupleC x where
   type ToITupleP x
   toITupleC :: x -> ToITupleP x
-instance (GL.TypeError ('GL.Text "ToITupleC: inductive tuple cannot be empty")) => ToITupleC () where
+instance (GL.TypeError ('GL.Text "ToITupleC: invalid empty tuple")) => ToITupleC () where
   type ToITupleP () = ()
   toITupleC () = ()
 instance ToITupleC (a,b) where
@@ -357,6 +356,56 @@   type ToITupleP (a,b,c,d,e,f,g,h,i,j,k,l) = (a,(b,(c,(d,(e,(f,(g,(h,(i,(j,(k,(l,()))))))))))))
   toITupleC (a,b,c,d,e,f,g,h,i,j,k,l) = (a,(b,(c,(d,(e,(f,(g,(h,(i,(j,(k,(l,()))))))))))))
 
+-- | takes an inductive tuple and creates a flat n-tuple
+--
+-- >>> fromITupleC (123,('x',(False,("abc",()))))
+-- (123,'x',False,"abc")
+--
+-- >>> fromITupleC (123,('x',()))
+-- (123,'x')
+--
+class FromITupleC x where
+  type FromITupleP x
+  fromITupleC :: x -> FromITupleP x
+instance FromITupleC () where
+  type FromITupleP () = ()
+  fromITupleC () = ()
+instance FromITupleC (a,()) where
+  type FromITupleP (a,()) = a
+  fromITupleC (a,()) = a
+instance FromITupleC (a,(b,())) where
+  type FromITupleP (a,(b,())) = (a,b)
+  fromITupleC (a,(b,())) = (a,b)
+instance FromITupleC (a,(b,(c,()))) where
+  type FromITupleP (a,(b,(c,()))) = (a,b,c)
+  fromITupleC (a,(b,(c,()))) = (a,b,c)
+instance FromITupleC (a,(b,(c,(d,())))) where
+  type FromITupleP (a,(b,(c,(d,())))) = (a,b,c,d)
+  fromITupleC (a,(b,(c,(d,())))) = (a,b,c,d)
+instance FromITupleC (a,(b,(c,(d,(e,()))))) where
+  type FromITupleP (a,(b,(c,(d,(e,()))))) = (a,b,c,d,e)
+  fromITupleC (a,(b,(c,(d,(e,()))))) = (a,b,c,d,e)
+instance FromITupleC (a,(b,(c,(d,(e,(f,())))))) where
+  type FromITupleP (a,(b,(c,(d,(e,(f,())))))) = (a,b,c,d,e,f)
+  fromITupleC (a,(b,(c,(d,(e,(f,())))))) = (a,b,c,d,e,f)
+instance FromITupleC (a,(b,(c,(d,(e,(f,(g,()))))))) where
+  type FromITupleP (a,(b,(c,(d,(e,(f,(g,()))))))) = (a,b,c,d,e,f,g)
+  fromITupleC (a,(b,(c,(d,(e,(f,(g,()))))))) = (a,b,c,d,e,f,g)
+instance FromITupleC (a,(b,(c,(d,(e,(f,(g,(h,())))))))) where
+  type FromITupleP (a,(b,(c,(d,(e,(f,(g,(h,())))))))) = (a,b,c,d,e,f,g,h)
+  fromITupleC (a,(b,(c,(d,(e,(f,(g,(h,())))))))) = (a,b,c,d,e,f,g,h)
+instance FromITupleC (a,(b,(c,(d,(e,(f,(g,(h,(i,()))))))))) where
+  type FromITupleP (a,(b,(c,(d,(e,(f,(g,(h,(i,()))))))))) = (a,b,c,d,e,f,g,h,i)
+  fromITupleC (a,(b,(c,(d,(e,(f,(g,(h,(i,()))))))))) = (a,b,c,d,e,f,g,h,i)
+instance FromITupleC (a,(b,(c,(d,(e,(f,(g,(h,(i,(j,())))))))))) where
+  type FromITupleP (a,(b,(c,(d,(e,(f,(g,(h,(i,(j,())))))))))) = (a,b,c,d,e,f,g,h,i,j)
+  fromITupleC (a,(b,(c,(d,(e,(f,(g,(h,(i,(j,())))))))))) = (a,b,c,d,e,f,g,h,i,j)
+instance FromITupleC (a,(b,(c,(d,(e,(f,(g,(h,(i,(j,(k,()))))))))))) where
+  type FromITupleP (a,(b,(c,(d,(e,(f,(g,(h,(i,(j,(k,()))))))))))) = (a,b,c,d,e,f,g,h,i,j,k)
+  fromITupleC (a,(b,(c,(d,(e,(f,(g,(h,(i,(j,(k,()))))))))))) = (a,b,c,d,e,f,g,h,i,j,k)
+instance FromITupleC (a,(b,(c,(d,(e,(f,(g,(h,(i,(j,(k,(l,())))))))))))) where
+  type FromITupleP (a,(b,(c,(d,(e,(f,(g,(h,(i,(j,(k,(l,())))))))))))) = (a,b,c,d,e,f,g,h,i,j,k,l)
+  fromITupleC (a,(b,(c,(d,(e,(f,(g,(h,(i,(j,(k,(l,())))))))))))) = (a,b,c,d,e,f,g,h,i,j,k,l)
 
 -- | takes a list of size @n@ and converts it to an inductive tuple. see 'Predicate.Data.ReadShow.PrintL'
 --
@@ -630,7 +679,7 @@ p ~> q = not p || q
 infixr 1 ~>
 
--- | extract the first element from a n-tuple
+-- | extract element 1 from a n-tuple
 class ExtractL1C tp where
   type ExtractL1T tp
   extractL1C :: tp -> ExtractL1T tp
@@ -656,7 +705,7 @@   type ExtractL1T (a,b,c,d,e,f,g,h) = a
   extractL1C (a,_,_,_,_,_,_,_) = a
 
--- | extract the second element from a n-tuple
+-- | extract element 2 from a n-tuple
 class ExtractL2C tp where
   type ExtractL2T tp
   extractL2C :: tp -> ExtractL2T tp
@@ -682,13 +731,13 @@   type ExtractL2T (a,b,c,d,e,f,g,h) = b
   extractL2C (_,b,_,_,_,_,_,_) = b
 
--- | extract the third element from a n-tuple
+-- | extract element 3 from a n-tuple
 class ExtractL3C tp where
   type ExtractL3T tp
   extractL3C :: tp -> ExtractL3T tp
 instance ExtractL3C (a,b) where
-  type ExtractL3T (a,b) = GL.TypeError ('GL.Text "Thd doesn't work for 2-tuples")
-  extractL3C _ = errorInProgram "Thd doesn't work for 2-tuples"
+  type ExtractL3T (a,b) = GL.TypeError ('GL.Text "L3 doesn't work for 2-tuples")
+  extractL3C _ = errorInProgram "L3 doesn't work for 2-tuples"
 instance ExtractL3C (a,b,c) where
   type ExtractL3T (a,b,c) = c
   extractL3C (_,_,c) = c
@@ -708,7 +757,7 @@   type ExtractL3T (a,b,c,d,e,f,g,h) = c
   extractL3C (_,_,c,_,_,_,_,_) = c
 
--- | extract the fourth element from a n-tuple
+-- | extract element 4 from a n-tuple
 class ExtractL4C tp where
   type ExtractL4T tp
   extractL4C :: tp -> ExtractL4T tp
@@ -734,7 +783,7 @@   type ExtractL4T (a,b,c,d,e,f,g,h) = d
   extractL4C (_,_,_,d,_,_,_,_) = d
 
--- | extract the fifth element from a n-tuple
+-- | extract element 5 from a n-tuple
 class ExtractL5C tp where
   type ExtractL5T tp
   extractL5C :: tp -> ExtractL5T tp
@@ -760,7 +809,7 @@   type ExtractL5T (a,b,c,d,e,f,g,h) = e
   extractL5C (_,_,_,_,e,_,_,_) = e
 
--- | extract the sixth element from a n-tuple
+-- | extract element 6 from a n-tuple
 class ExtractL6C tp where
   type ExtractL6T tp
   extractL6C :: tp -> ExtractL6T tp
@@ -786,7 +835,7 @@   type ExtractL6T (a,b,c,d,e,f,g,h) = f
   extractL6C (_,_,_,_,_,f,_,_) = f
 
--- | extract the seventh element from a n-tuple
+-- | extract element 7 from a n-tuple
 class ExtractL7C tp where
   type ExtractL7T tp
   extractL7C :: tp -> ExtractL7T tp
@@ -812,7 +861,7 @@   type ExtractL7T (a,b,c,d,e,f,g,h) = g
   extractL7C (_,_,_,_,_,_,g,_) = g
 
--- | extract the eighth element from a n-tuple
+-- | extract element 8 from a n-tuple
 class ExtractL8C tp where
   type ExtractL8T tp
   extractL8C :: tp -> ExtractL8T tp
@@ -956,8 +1005,13 @@   where
     isPrime' [] _ = errorInProgram "primes is empty"
     isPrime' (p:ps) n = p*p > n || n `rem` p /= 0 && isPrime' ps n
-    primes' = 7 : filter (isPrime' primes') (scanl (+) 11 $ cycle [2,4,2,4,6,2,6,4])
+    primes' = 7 : filter (isPrime' primes') (scanl (+) 11 $ cycle' [2,4,2,4,6,2,6,4])
 
+-- | similar to 'cycle' but if the list is empty will return an empty list
+cycle' :: [a] -> [a]
+cycle' [] = []
+cycle' xs = xs' where xs' = xs ++ xs'
+
 -- | pretty print 'Ordering'
 prettyOrd :: Ordering -> String
 prettyOrd = \case
@@ -1219,12 +1273,6 @@ 
     shift one other = zipWith (++) (one : repeat other)
 
-asProxyRight :: proxy a -> proxy1 a -> proxy1 a
-asProxyRight = flip const
-
-asProxyLeft :: proxy a -> proxy1 a -> proxy a
-asProxyLeft = const
-
 -- | strip ansi characters from a string and print it (for doctests)
 removeAnsi :: Show a => Either String a -> IO ()
 removeAnsi = putStrLn . removeAnsiImpl
@@ -1243,6 +1291,7 @@                in concat $ unfoldr f e
      Right a -> show a
 
+-- | 'Identity' lens
 _Id :: Lens (Identity a) (Identity b) a b
 _Id afb (Identity a) = Identity <$> afb a
 
@@ -1270,9 +1319,11 @@ instance SwapC ((,,,,,,) a b c d e) where
   swapC (a,b,c,d,e,f,g) = (a,b,c,d,e,g,f)
 
+-- | strict version of 'sum'
 sum' :: (Foldable t, Num a) => t a -> a
 sum' = foldl' (+) 0
 
+-- | strict version of 'product'
 product' :: (Foldable t, Num a) => t a -> a
 product' = foldl' (*) 1
 
src/Predicate/Refined.hs view
@@ -71,7 +71,7 @@   deriving stock (Show, TH.Lift)
   deriving newtype (Eq, Ord, NFData)
 
--- | extract the value from Refined
+-- | extract the value from 'Refined'
 unRefined :: forall k (opts :: Opt) (p :: k) a
    . Refined opts p a
   -> a
@@ -87,10 +87,11 @@ -- >>> pureTryTest $ fromString @(Refined OL (ReadP Int Id >> Id > 244) String) "52"
 -- Left ()
 --
-instance RefinedC opts p String => IsString (Refined opts p String) where
+instance RefinedC opts p String
+      => IsString (Refined opts p String) where
   fromString s =
     case newRefined @opts @p s of
-      Left w -> error $ "Refined(fromString):" ++ errorDisplay (getOpt @opts) w
+      Left w -> error $ "Refined(IsString:fromString):" ++ errorDisplay (getOpt @opts) w
       Right r -> r
 
 errorDisplay :: POpts -> Msg0 -> String
@@ -238,18 +239,21 @@           Just a -> pure $ unsafeRefined a
   in f 0
 
+-- | holds the results of creating a 'Refined' value for display
 data Msg0 = Msg0 { m0BoolE :: !(Either String Bool)
                  , m0Short :: !String
                  , m0Long :: !String
                  , m0ValBoolColor :: !String
                  } deriving Eq
 
+-- | verbose display of 'Msg0'
 showMsg0 :: Msg0 -> String
 showMsg0 (Msg0 a b c d) = "Msg0 [" ++ show a ++ "]\nShort[" ++ b ++ "]\nLong[" ++ c ++ "]\nColor[" ++ d ++ "]"
 
 instance Show Msg0 where
   show = m0Long
 
+-- | returns a 'Refined' value if @a@ is valid for the predicate @p@ for any 'MonadEval' instance
 newRefined' :: forall opts p a m
    . ( MonadEval m
      , RefinedC opts p a
@@ -259,14 +263,14 @@ newRefined' a = do
   let o = getOpt @opts
   pp <- evalBool (Proxy @p) o a
-  let r = colorValBool o (_ttVal pp)
+  let r = colorValBool o (pp ^. ttVal)
       s = prtTree o pp
       msg0 = Msg0 (pp ^. ttVal . _ValEither) (topMessage pp) s r
   pure $ case getValueLR NoInline o "" pp [] of
        Right True -> Right (Refined a)
        _ -> Left msg0
 
--- | returns a 'Refined' value if @a@ is valid for the predicate @p@
+-- | returns a pure 'Refined' value if @a@ is valid for the predicate @p@
 --
 -- >>> newRefined @OL @(ReadP Int Id > 99) "123"
 -- Right (Refined "123")
@@ -322,7 +326,6 @@ -- >>> newRefined @OU @((Id $$ 13) > 100) (\x -> x * 14) ^? _Right . to unRefined . to ($ 99)
 -- Just 1386
 --
-
 newRefined :: forall opts p a
     . RefinedC opts p a
    => a
@@ -344,7 +347,7 @@   in case getValueLR NoInline o "" tt [] of
        Right True -> Refined a
        _ -> let s = prtTree o tt
-                bp = colorValBool o (_ttVal tt)
+                bp = colorValBool o (tt ^. ttVal)
             in case oDebug o of
                  DZero -> error bp
                  DLite -> error $ bp ++ nullIf "\n" s
src/Predicate/Refined2.hs view
@@ -97,9 +97,11 @@ --
 data Refined2 (opts :: Opt) ip op i = Refined2 !(PP ip i) !i
 
+-- | field accessor for the converted input value in 'Refined2'
 r2In :: Refined2 (opts :: Opt) ip op i -> PP ip i
 r2In (Refined2 ppi _) = ppi
 
+-- | field accessor for the original input value in 'Refined2'
 r2Out :: Refined2 (opts :: Opt) ip op i -> i
 r2Out (Refined2 _ i) = i
 
@@ -168,7 +170,7 @@          ) => IsString (Refined2 opts ip op i) where
   fromString i =
     case newRefined2 i of
-      Left e -> error $ "Refined2(fromString):" ++ show e
+      Left e -> error $ "Refined2(IsString:fromString):" ++ show e
       Right r -> r
 
 -- read instance from -ddump-deriv
@@ -230,7 +232,7 @@ -- Right (Refined2 254 "00fe")
 --
 -- >>> removeAnsi $ A.eitherDecode' @(Refined2 OAN (ReadBase Int 16) (Id > 10 && Id < 256) String) "\"00fe443a\""
--- Error in $: Refined2:Step 2. False Boolean Check(op) | {True && False | (16663610 < 256)}
+-- Error in $: Refined2(FromJSON:parseJSON):Step 2. False Boolean Check(op) | {True && False | (16663610 < 256)}
 -- *** Step 1. Success Initial Conversion(ip) (16663610) ***
 -- P ReadBase(Int,16) 16663610
 -- |
@@ -257,7 +259,7 @@   parseJSON z = do
                   i <- parseJSON @i z
                   case newRefined2 i of
-                    Left e -> fail $ "Refined2:" ++ show e
+                    Left e -> fail $ "Refined2(FromJSON:parseJSON):" ++ show e
                     Right r -> return r
 
 -- | 'Arbitrary' instance for 'Refined2'
@@ -327,7 +329,7 @@ -- Refined2 2019-04-23 "2019-04-23"
 --
 -- >>> removeAnsi $ (view _3 +++ view _3) $ B.decodeOrFail @K2 (B.encode r)
--- Refined2:Step 2. False Boolean Check(op) | {2019-05-30 <= 2019-04-23}
+-- Refined2(Binary:get):Step 2. False Boolean Check(op) | {2019-05-30 <= 2019-04-23}
 -- *** Step 1. Success Initial Conversion(ip) (2019-04-23) ***
 -- P ReadP Day 2019-04-23
 -- |
@@ -352,7 +354,7 @@   get = do
           i <- B.get @i
           case newRefined2 i of
-            Left e -> fail $ "Refined2:" ++ show e
+            Left e -> fail $ "Refined2(Binary:get):" ++ show e
             Right r -> return r
   put (Refined2 _ r) = B.put @i r
 
@@ -370,6 +372,7 @@      | RTTrue !a !(Tree PE) !(Tree PE) -- op true
      deriving Show
 
+-- | version for creating a 'Refined2' value that works for any 'MonadEval' instance
 newRefined2' :: forall opts ip op i m
   . ( MonadEval m
     , Refined2C opts ip op i
@@ -379,7 +382,7 @@   -> m (Either Msg2 (Refined2 opts ip op i))
 newRefined2' = newRefined2P' Proxy
 
--- | same as 'newRefined2P' but runs in IO
+-- | same as 'newRefined2P' but runs for any MonadEval instance
 newRefined2P' :: forall opts ip op i proxy m
   . ( MonadEval m
     , Refined2C opts ip op i
@@ -392,13 +395,13 @@   (ret,mr) <- eval2M i
   return $ maybe (Left $ prt2Impl (getOpt @opts) ret) Right mr
 
--- | pure version for extracting Refined2
+-- | pure version for creating a 'Refined2' value
 --
 -- >>> newRefined2 @OZ @(ReadBase Int 16) @(Lt 255) "00fe"
 -- Right (Refined2 254 "00fe")
 --
--- >>> newRefined2 @OZ @(ReadBase Int 16) @(GuardBool (PrintF "0x%X is too large" Id) (Lt 253)) "00fe"
--- Left Step 2. Failed Boolean Check(op) | 0xFE is too large
+-- >>> newRefined2 @OZ @(ReadBase Int 16) @(GuardBool (PrintF "%#x is too large" Id) (Lt 253)) "00fe"
+-- Left Step 2. Failed Boolean Check(op) | 0xfe is too large
 --
 -- >>> newRefined2 @OZ @(ReadBase Int 16) @(Lt 255) "00fg"
 -- Left Step 1. Failed Initial Conversion(ip) | invalid base 16
@@ -438,6 +441,15 @@     -> Either Msg2 (Refined2 opts ip op i)
 newRefined2 = newRefined2P Proxy
 
+-- | create a Refined2 using a 4-tuple proxy and aggregate the results on failure
+--
+-- >>> type T4 k = '(OZ, MkDayExtra Id >> 'Just Id, GuardBool "expected a Sunday" (Thd == 7), k)
+-- >>> newRefined2P (Proxy @(T4 _)) (2019,10,12)
+-- Left Step 2. Failed Boolean Check(op) | expected a Sunday
+--
+-- >>> newRefined2P (Proxy @(T4 _)) (2019,10,13)
+-- Right (Refined2 (2019-10-13,41,7) (2019,10,13))
+--
 newRefined2P :: forall opts ip op i
   . ( Refined2C opts ip op i
     , Show (PP ip i)
@@ -448,6 +460,7 @@   let (ret,mr) = runIdentity $ eval2M i
   in maybe (Left $ prt2Impl (getOpt @opts) ret) Right mr
 
+-- | create a Refined2 value using a 4-tuple proxy (see 'mkProxy2')
 eval2P :: forall opts ip op i m
   . ( Refined2C opts ip op i
     , MonadEval m
@@ -457,6 +470,7 @@   -> m (RResults2 (PP ip i), Maybe (Refined2 opts ip op i))
 eval2P _ = eval2M
 
+-- | workhorse for creating 'Refined2' values
 eval2M :: forall opts ip op i m
   . ( MonadEval m
     , Refined2C opts ip op i
@@ -475,6 +489,7 @@       (Left e,t2) -> (RTF a t1 e t2, Nothing)
    (Left e,t1) -> pure (RF e t1, Nothing)
 
+-- | holds the results of creating a 'Refined2' value for display
 data Msg2 = Msg2 { m2Desc :: !String
                  , m2Short :: !String
                  , m2Long :: !String
@@ -484,6 +499,7 @@ instance Show Msg2 where
   show (Msg2 a b c _d) = a <> nullIf " | " b <> nullIf "\n" c
 
+-- | format the output from creating a 'Refined2' value into 'Msg2'
 prt2Impl :: forall a . Show a
   => POpts
   -> RResults2 a
src/Predicate/Refined3.hs view
@@ -54,7 +54,6 @@   , mkProxy3
   , mkProxy3'
   , MakeR3
-  , MakeR3'
 
   -- ** unsafe methods for creating Refined3
   , unsafeRefined3
@@ -118,9 +117,11 @@ 
 type role Refined3 phantom nominal nominal nominal nominal
 
+-- | field accessor for the converted input value in 'Refined3'
 r3In :: Refined3 opts ip op fmt i -> PP ip i
 r3In (Refined3 ppi _) = ppi
 
+-- | field accessor for the converted output value in 'Refined3'
 r3Out :: Refined3 opts ip op fmt i -> i
 r3Out (Refined3 _ i) = i
 
@@ -190,7 +191,7 @@          ) => IsString (Refined3 opts ip op fmt String) where
   fromString s =
     case newRefined3 s of
-      Left e -> error $ "Refined3(fromString):" ++ show e
+      Left e -> error $ "Refined3(IsString:fromString):" ++ show e
       Right r -> r
 
 -- read instance from -ddump-deriv
@@ -253,7 +254,7 @@ -- Right (Refined3 254 "fe")
 --
 -- >>> removeAnsi $ A.eitherDecode' @(Refined3 OAN (ReadBase Int 16) (Id > 10 && Id < 256) (ShowBase 16) String) "\"00fe443a\""
--- Error in $: Refined3:Step 2. False Boolean Check(op) | {True && False | (16663610 < 256)}
+-- Error in $: Refined3(FromJSON:parseJSON):Step 2. False Boolean Check(op) | {True && False | (16663610 < 256)}
 -- *** Step 1. Success Initial Conversion(ip) (16663610) ***
 -- P ReadBase(Int,16) 16663610
 -- |
@@ -280,7 +281,7 @@   parseJSON z = do
                   i <- parseJSON @i z
                   case newRefined3 i of
-                    Left e -> fail $ "Refined3:" ++ show e
+                    Left e -> fail $ "Refined3(FromJSON:parseJSON):" ++ show e
                     Right r -> return r
 
 -- | 'Arbitrary' instance for 'Refined3'
@@ -346,7 +347,7 @@ -- Refined3 2019-04-23 "2019-04-23"
 --
 -- >>> removeAnsi $ (view _3 +++ view _3) $ B.decodeOrFail @K2 (B.encode r)
--- Refined3:Step 2. False Boolean Check(op) | {2019-05-30 <= 2019-04-23}
+-- Refined3(Binary:get):Step 2. False Boolean Check(op) | {2019-05-30 <= 2019-04-23}
 -- *** Step 1. Success Initial Conversion(ip) (2019-04-23) ***
 -- P ReadP Day 2019-04-23
 -- |
@@ -371,7 +372,7 @@   get = do
           i <- B.get @i
           case newRefined3 i of
-            Left e -> fail $ "Refined3:" ++ show e
+            Left e -> fail $ "Refined3(Binary:get):" ++ show e
             Right r -> return r
   put (Refined3 _ r) = B.put @i r
 
@@ -414,9 +415,6 @@ type family MakeR3 p where
   MakeR3 '(opts,ip,op,fmt,i) = Refined3 opts ip op fmt i
 
-type family MakeR3' opts p where
-  MakeR3' opts '(ip,op,fmt,i) = Refined3 opts ip op fmt i
-
 -- | An ADT that summarises the results of evaluating Refined3 representing all possible states
 data RResults3 a =
        RF !String !(Tree PE)        -- Left e
@@ -436,7 +434,7 @@   -> m (Either Msg3 (Refined3 opts ip op fmt i))
 newRefined3' = newRefined3P' Proxy
 
--- | same as 'newRefined3P' but runs in IO
+-- | same as 'newRefined3P' but runs in any MonadEval instance
 newRefined3P' :: forall opts ip op fmt i proxy m
   . ( MonadEval m
     , Refined3C opts ip op fmt i
@@ -454,8 +452,8 @@ -- >>> newRefined3 @OZ @(ReadBase Int 16) @(Lt 255) @(PrintF "%x" Id) "00fe"
 -- Right (Refined3 254 "fe")
 --
--- >>> newRefined3 @OZ @(ReadBase Int 16) @(GuardBool (PrintF "0x%X is too large" Id) (Lt 253)) @(PrintF "%x" Id) "00fe"
--- Left Step 2. Failed Boolean Check(op) | 0xFE is too large
+-- >>> newRefined3 @OZ @(ReadBase Int 16) @(GuardBool (PrintF "%#x is too large" Id) (Lt 253)) @(PrintF "%x" Id) "00fe"
+-- Left Step 2. Failed Boolean Check(op) | 0xfe is too large
 --
 -- >>> newRefined3 @OZ @(ReadBase Int 16) @(Lt 255) @(PrintF "%x" Id) "00fg"
 -- Left Step 1. Failed Initial Conversion(ip) | invalid base 16
@@ -536,6 +534,7 @@   -> m (RResults3 (PP ip i), Maybe (Refined3 opts ip op fmt i))
 eval3P _ = eval3M
 
+-- | workhorse for creating 'Refined3' values
 eval3M :: forall opts ip op fmt i m
   . ( MonadEval m
     , Refined3C opts ip op fmt i
@@ -558,7 +557,7 @@       (Left e,t2) -> pure (RTF a t1 e t2, Nothing)
    (Left e,t1) -> pure (RF e t1, Nothing)
 
--- | creates Refined3 value but skips the initial conversion
+-- | creates a 'Refined3' value but skips the initial conversion
 eval3MSkip :: forall opts ip op fmt i m
   . ( MonadEval m
     , Refined3C opts ip op fmt i
@@ -580,6 +579,7 @@ mkNodeSkipP :: Tree PE
 mkNodeSkipP = Node (PE TrueP "skipped PP ip i = Id") []
 
+-- | holds the results of creating a 'Refined3' value for display
 data Msg3 = Msg3 { m3Desc :: !String
                  , m3Short :: !String
                  , m3Long :: !String
src/Predicate/Refined5.hs view
@@ -148,7 +148,7 @@          ) => IsString (Refined5 opts ip op i) where
   fromString i =
     case newRefined5 i of
-      Left e -> error $ "Refined5(fromString):" ++ show e
+      Left e -> error $ "Refined5(IsString:fromString):" ++ show e
       Right r -> r
 
 -- read instance from -ddump-deriv
@@ -210,14 +210,14 @@ -- Right (Refined5 123)
 --
 -- >>> removeAnsi $ A.eitherDecode' @(Refined5 OL (ReadBase Int 16) (Id > 10 && Id < 256) String) "9"
--- Error in $: Refined5:false boolean check | {False && True | (9 > 10)}
+-- Error in $: Refined5(FromJSON:parseJSON):false boolean check | {False && True | (9 > 10)}
 -- False
 --
 -- >>> A.eitherDecode' @(Refined5 OZ (ReadBase Int 16) (Id > 10 && Id < 256) String) "254"
 -- Right (Refined5 254)
 --
 -- >>> removeAnsi $ A.eitherDecode' @(Refined5 OAN (ReadBase Int 16) (Id > 10 && Id < 256) String) "12345"
--- Error in $: Refined5:false boolean check | {True && False | (12345 < 256)}
+-- Error in $: Refined5(FromJSON:parseJSON):false boolean check | {True && False | (12345 < 256)}
 -- False True && False | (12345 < 256)
 -- |
 -- +- True 12345 > 10
@@ -238,7 +238,7 @@   parseJSON z = do
                   i <- parseJSON @(PP ip i) z
                   case evalBool5 @opts @op i of
-                    Left e -> fail $ "Refined5:" ++ e
+                    Left e -> fail $ "Refined5(FromJSON:parseJSON):" ++ e
                     Right _ -> return (Refined5 i)
 
 -- | 'Arbitrary' instance for 'Refined5'
@@ -293,7 +293,7 @@   get = do
           i <- B.get @(PP ip i)
           case evalBool5 @opts @op i of
-            Left e -> fail $ "Refined5:Binary:" ++ e
+            Left e -> fail $ "Refined5(Binary:get):" ++ e
             Right _ -> return $ Refined5 i
   put (Refined5 r) = B.put @(PP ip i) r
 
@@ -303,6 +303,7 @@          ) => Hashable (Refined5 opts ip op i) where
   hashWithSalt s (Refined5 b) = s + hash b
 
+-- | creating a 'Refined5' value for any 'MonadEval'
 newRefined5' :: forall opts ip op i m
   . ( MonadEval m
     , Refined2C opts ip op i
@@ -312,7 +313,7 @@   -> m (Either Msg2 (Refined5 opts ip op i))
 newRefined5' = newRefined5P' Proxy
 
--- | same as 'newRefined5P' but runs in IO
+-- | same as 'newRefined5P' but runs for any MonadEval instance
 newRefined5P' :: forall opts ip op i proxy m
   . ( MonadEval m
     , Refined2C opts ip op i
@@ -325,13 +326,13 @@   (ret,mr) <- eval5M i
   return $ maybe (Left $ prt2Impl (getOpt @opts) ret) Right mr
 
--- | pure version for extracting Refined5
+-- | pure version for creating a 'Refined5' value
 --
 -- >>> newRefined5 @OZ @(ReadBase Int 16) @(Lt 255) "00fe"
 -- Right (Refined5 254)
 --
--- >>> newRefined5 @OZ @(ReadBase Int 16) @(GuardBool (PrintF "0x%X is too large" Id) (Lt 253)) "00fe"
--- Left Step 2. Failed Boolean Check(op) | 0xFE is too large
+-- >>> newRefined5 @OZ @(ReadBase Int 16) @(GuardBool (PrintF "%#x is too large" Id) (Lt 253)) "00fe"
+-- Left Step 2. Failed Boolean Check(op) | 0xfe is too large
 --
 -- >>> newRefined5 @OZ @(ReadBase Int 16) @(Lt 255) "00fg"
 -- Left Step 1. Failed Initial Conversion(ip) | invalid base 16
@@ -371,6 +372,7 @@     -> Either Msg2 (Refined5 opts ip op i)
 newRefined5 = newRefined5P Proxy
 
+-- | create a Refined5 using a 4-tuple proxy and aggregate the results on failure
 newRefined5P :: forall opts ip op i
   . ( Refined2C opts ip op i
     , Show (PP ip i)
@@ -381,6 +383,7 @@   let (ret,mr) = runIdentity $ eval5M i
   in maybe (Left $ prt2Impl (getOpt @opts) ret) Right mr
 
+-- | create a 'Refined5' value using a 4-tuple proxy (see 'Predicate.Refined2.mkProxy2')
 eval5P :: forall opts ip op i m
   . ( Refined2C opts ip op i
     , MonadEval m
@@ -390,6 +393,7 @@   -> m (RResults2 (PP ip i), Maybe (Refined5 opts ip op i))
 eval5P _ = eval5M
 
+-- | workhorse for creating 'Refined5' values
 eval5M :: forall opts ip op i m
   . ( MonadEval m
     , Refined2C opts ip op i
src/Predicate/Util.hs view
@@ -28,14 +28,10 @@     Val(..)
   , _Fail
   , _Val
-  , _True
-  , _False
   , _ValEither
-  , val2P
-  , val2PBool
 
   -- ** TT typed tree
-  , TT(..)
+  , TT
   , ttVal
   , ttValBool
   , ttString
@@ -136,7 +132,6 @@   , chkSize
   , chkSize2
   , badLength
-
   ) where
 import Predicate.Misc
 import GHC.TypeLits (Symbol, Nat, KnownSymbol, KnownNat)
@@ -216,11 +211,14 @@ -- | semigroup for ValP
 --
 -- >>> TrueP <> FalseP <> ValP
--- ValP
+-- FalseP
 --
 -- >>> ValP <> TrueP <> FalseP
 -- FalseP
 --
+-- >>> ValP <> TrueP <> ValP
+-- TrueP
+--
 -- >>> FailP "abc" <> (TrueP <> FalseP) <> FailP "def"
 -- FailP "abc | def"
 --
@@ -240,9 +238,11 @@    FailP s <> FailP s1 = FailP (jamSS s s1)
    FailP s <> _ = FailP s
    _ <> FailP s = FailP s
-   _ <> ValP = ValP
-   _ <> TrueP = TrueP
+   FalseP <> _ = FalseP
    _ <> FalseP = FalseP
+   TrueP <> _ = TrueP
+   _ <> TrueP = TrueP
+   ValP <> ValP = ValP
 
 instance Monoid ValP where
   mempty = ValP
@@ -328,7 +328,7 @@                , _ttString :: !String  -- ^ detailed information eg input and output and text
                , _ttForest :: !(Forest PE) -- ^ the child nodes
                } deriving stock (Functor, Read, Show, Eq, Foldable, Traversable, Generic, Generic1)
-                 deriving TH.Lift
+                 deriving stock TH.Lift
 
 -- dont expose lenses for _ttValP and _ttVal as they must be kept in sync: see ttVal
 makeLensesFor [("_ttString","ttString"),("_ttForest","ttForest")] ''TT
@@ -341,16 +341,20 @@    mempty = TT mempty mempty mempty mempty
 
 instance Applicative TT where
-  pure a = TT ValP (pure a) "" []
+  pure a = TT ValP (Val a) "" []
   (<*>) = ap
 
+fixTTValP :: ValP -> TT a -> TT a
+fixTTValP bp tt = tt { _ttValP = bp <> _ttValP tt }
+
 instance Monad TT where
   return = pure
-  z@(TT _ bt ss ts) >>= amb =
+  z@(TT bp bt ss ts) >>= amb =
      case bt of
-       Val a -> amb a & ttString %~ jamSS ss
-                      & ttForest %~ (ts <>)
-       Fail e -> z & ttVal .~ Fail e
+       Val a -> fixTTValP bp $ amb a
+                  & ttString %~ jamSS ss
+                  & ttForest %~ (ts <>)
+       Fail e -> z { _ttVal = Fail e }
 
 -- | creates a Node for the evaluation tree
 mkNodeCopy :: POpts
@@ -366,7 +370,7 @@        -> String
        -> [Tree PE]
        -> TT a
-mkNode opts = mkNodeImpl opts . (view val2P &&& id)
+mkNode opts = mkNodeImpl opts . (val2P &&& id)
 
 -- | creates a Node for the evaluation tree
 mkNodeImpl :: POpts
@@ -792,7 +796,7 @@    -> Val Bool
    -> String
 colorValBool o r =
-  let f = colorMe o (r ^. val2PBool)
+  let f = colorMe o (val2PBool r)
   in case r of
       Fail e -> f "Fail" <> " " <> e
       Val False -> f "False"
@@ -1147,44 +1151,6 @@   | isVerbose o = [hh tt]
   | otherwise = []
 
--- | prism for Val True
---
--- >>> Val True ^? _True
--- Just ()
---
--- >>> Val False ^? _True
--- Nothing
---
-_True :: a ~ Bool => Prism' (Val a) ()
-_True =
-  prism' (const (Val True))
-  $ \case
-       Val True -> Just ()
-       Val False -> Nothing
-       Fail {} -> Nothing
-
--- | prism for Val False
---
--- >>> (_True # ()) ^? _True
--- Just ()
---
--- >>> (_False # ()) ^? _False
--- Just ()
---
--- >>> Val False ^? _False
--- Just ()
---
--- >>> Val True ^? _False
--- Nothing
---
-_False :: a ~ Bool => Prism' (Val a) ()
-_False =
-  prism' (const (Val False))
-  $ \case
-       Val False -> Just ()
-       Val True -> Nothing
-       Fail {} -> Nothing
-
 -- | iso for 'Val'
 --
 -- >>> Val 123 ^. _ValEither
@@ -1224,40 +1190,40 @@                Fail e -> Left e
         bw = either Fail Val
 
--- | a lens from typed 'Val' to the untyped 'ValP'
+-- | converts from a typed 'Val' to the untyped 'ValP'
 --
--- >>> Val True ^. val2P
+-- >>> val2P (Val True)
 -- ValP
 --
--- >>> Val 123 ^. val2P
+-- >>> val2P (Val 123)
 -- ValP
 --
--- >>> Fail "abc" ^. val2P
+-- >>> val2P (Fail "abc")
 -- FailP "abc"
 --
-val2P :: Lens' (Val a) ValP
-val2P afb bt = bt <$ afb r
-  where r = case bt of
-              Fail e -> FailP e
-              Val {} -> ValP
+val2P :: Val a -> ValP
+val2P =
+  \case
+    Fail e -> FailP e
+    Val {} -> ValP
 
--- | a lens from typed 'Val' Bool to the untyped 'ValP'
+-- | converts from a typed 'Val' Bool to the untyped 'ValP'
 --
--- >>> Val True ^. val2PBool
+-- >>> val2PBool (Val True)
 -- TrueP
 --
--- >>> Val False ^. val2PBool
+-- >>> val2PBool (Val False)
 -- FalseP
 --
--- >>> Fail "abc" ^. val2PBool
+-- >>> val2PBool (Fail "abc")
 -- FailP "abc"
 --
-val2PBool :: a ~ Bool => Lens' (Val a) ValP
-val2PBool afb bt = bt <$ afb r
-  where r = case bt of
-              Fail e -> FailP e
-              Val True -> TrueP
-              Val False -> FalseP
+val2PBool :: a ~ Bool => Val a -> ValP
+val2PBool =
+  \case
+    Fail e -> FailP e
+    Val True -> TrueP
+    Val False -> FalseP
 
 -- | lens that keeps 'ValP' in sync with 'Val' for TT Bool
 --
@@ -1274,11 +1240,7 @@ -- True
 --
 ttValBool :: a ~ Bool => Lens' (TT a) (Val Bool)
-ttValBool afb tt = (\b -> tt { _ttValP = f b, _ttVal = b }) <$> afb (_ttVal tt)
-  where f = \case
-               Fail e -> FailP e
-               Val True -> TrueP
-               Val False -> FalseP
+ttValBool afb tt = (\b -> tt { _ttValP = val2PBool b, _ttVal = b }) <$> afb (_ttVal tt)
 
 -- | lens from 'TT' to 'Val' that also keeps 'ValP' in sync with 'Val'
 --
@@ -1292,8 +1254,5 @@ -- True
 --
 ttVal :: Lens (TT a) (TT b) (Val a) (Val b)
-ttVal afb tt = (\b -> tt { _ttValP = f b, _ttVal = b }) <$> afb (_ttVal tt)
-  where f = \case
-               Fail e -> FailP e
-               Val {} -> ValP
+ttVal afb tt = (\b -> tt { _ttValP = val2P b, _ttVal = b }) <$> afb (_ttVal tt)
 
src/Predicate/Util_TH.hs view
@@ -72,6 +72,7 @@        Left m -> fail $ refinedFailMsg @opts msg0 m
        Right r -> [||r||]
 
+-- | creates a 'Refined.Refined' refinement type running in IO
 refinedTHIO :: forall opts p i
   . (TH.Lift i, RefinedC opts p i)
   => i
test/TestJson.hs view
@@ -33,7 +33,7 @@   , testCase "testperson1 bad lastname lowercase first letter" $ expectIO (testPerson1 @OAN 4) (expectLeftWith ["lastName1", "invalid name", "diaz"])
   , testCase "testperson1 bad first name lowercase first letter" $ expectIO (testPerson1 @OAN 6) (expectLeftWith ["firstName1", "not upper first(d)"])
   , testCase "testperson1 age 99 out of range" $ expectIO (testPerson1 @OAN 5) (expectLeftWith ["Error in $[0].age1"])
-  , testCase "parse fail person1" $ expectBT (Fail "ParseJsonFile [Person1 'OZ](test3.json) Error in $[0].ipaddress1: Refined3:Step 2. Failed Boolean Check(op) | octet 3 out of range 0-255 found 260") $ pz @(ParseJsonFile [Person1 'OZ] "test3.json") ()
+  , testCase "parse fail person1" $ expectBT (Fail "ParseJsonFile [Person1 'OZ](test3.json) Error in $[0].ipaddress1: Refined3(FromJSON:parseJSON):Step 2. Failed Boolean Check(op) | octet 3 out of range 0-255 found 260") $ pz @(ParseJsonFile [Person1 'OZ] "test3.json") ()
   , testCase "parse ok person1" $ expectBT (Val 5) $ pl @(ParseJsonFile [Person1 OAN] "test2.json" >> Len) ()
   , testCase "missing file" $ expectBT (Fail "ParseJsonFile [Person1 'OZ](test2.jsoxxxn) file does not exist") $ pl @(ParseJsonFile [Person1 'OZ] "test2.jsoxxxn" >> Len) ()