content: {-# LANGUAGE DataKinds, PolyKinds, TypeOperators, TypeFamilies, FlexibleContexts #-}
  {-# LANGUAGE Rank2Types, ScopedTypeVariables #-}
  {-# LANGUAGE TemplateHaskell #-}
  
  import Control.Lens
  import Data.Bits
  import Data.Extensible
  import Data.Extensible.Bits
  import Data.Int
  import Data.Proxy
  import Data.Word
  import GHC.TypeLits
  import Language.Haskell.TH (mkName)
  import Test.QuickCheck
  
  type Fields = ["a" >: Bool, "b" >: Word8, "c" >: Bool]
  
  mkFieldAs (mkName "_a") "a"
  mkFieldAs (mkName "_b") "b"
  mkFieldAs (mkName "_c") "c"
  
  
  prop_lensA1 x r = set _a x (BitProd r :: Rec) ^. _a == x
  prop_lensA2 b = let r = BitProd b :: Rec
    in set _a (r ^. _a) r == r
  prop_lensA3 b x y = let r = BitProd b :: Rec
    in set _a x (set _a y r) == set _a x r
  
  prop_lensB1 x r = set _b x (BitProd r :: Rec) ^. _b == x
  prop_lensB2 b = let r = BitProd b :: Rec
    in set _b (r ^. _b) r == r
  prop_lensB3 b x y = let r = BitProd b :: Rec
    in set _b x (set _b y r) == set _b x r
  
  prop_lensC1 x r = set _c x (BitProd r :: Rec) ^. _c == x
  prop_lensC2 b = let r = BitProd b :: Rec
    in set _c (r ^. _c) r == r
  prop_lensC3 b x y = let r = BitProd b :: Rec
    in set _c x (set _c y r) == set _c x r
  
  type Rec = BitRecord Word64 Fields
  
  focus :: forall a. (Eq a, Show a) => FromBits Word64 a => Word64 -> a -> Property
  focus x a = let w = fromIntegral $ natVal (Proxy :: Proxy (BitWidth a))
    in fromBits (x `shiftL` w .|. toBits a) === a
  
  clean :: forall a. Eq a => FromBits Word64 a => a -> Property
  clean a = let w = fromIntegral $ natVal (Proxy :: Proxy (BitWidth a))
    in toBits a `shiftR` w === (zeroBits :: Word64)
  
  prop_focus_Word8 :: Word64 -> Word8 -> Property
  prop_focus_Word8 = focus
  
  prop_clean_Word8 :: Word8 -> Property
  prop_clean_Word8 = clean
  
  prop_focus_Word16 :: Word64 -> Word16 -> Property
  prop_focus_Word16 = focus
  
  prop_clean_Word16 :: Word16 -> Property
  prop_clean_Word16 = clean
  
  prop_focus_Word32 :: Word64 -> Word32 -> Property
  prop_focus_Word32 = focus
  
  prop_clean_Word32 :: Word32 -> Property
  prop_clean_Word32 = clean
  
  prop_focus_Int8 :: Word64 -> Int8 -> Property
  prop_focus_Int8 = focus
  
  prop_clean_Int8 :: Int8 -> Property
  prop_clean_Int8 = clean
  
  prop_focus_Int16 :: Word64 -> Int16 -> Property
  prop_focus_Int16 = focus
  
  prop_clean_Int16 :: Int16 -> Property
  prop_clean_Int16 = clean
  
  prop_focus_Int32 :: Word64 -> Int32 -> Property
  prop_focus_Int32 = focus
  
  prop_clean_Int32 :: Int32 -> Property
  prop_clean_Int32 = clean
  
  prop_focus_Bool :: Word64 -> Bool -> Property
  prop_focus_Bool = focus
  
  prop_clean_Bool :: Bool -> Property
  prop_clean_Bool = clean
  
  return []
  main = $quickCheckAll
  