diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+0.4.7.1
+-------------------------------------------------
+* Fixed weird CPP errors on macOS 10.13.2 (#18)
+* Added `optFlag`, `optLastArg`, and `optionOptArg`
+
 0.4.7
 -------------------------------------------------
 * Made various optimisations to improve the compilation time
diff --git a/examples/eff.hs b/examples/eff.hs
deleted file mode 100644
--- a/examples/eff.hs
+++ /dev/null
@@ -1,23 +0,0 @@
-{-# LANGUAGE TypeApplications, OverloadedLabels, PolyKinds, DataKinds, ScopedTypeVariables, Rank2Types #-}
-import Data.Extensible
-
-import Prelude hiding (readFile)
-import Control.Exception
-import Data.ByteString (ByteString)
-
-data FileSystem r where
-  ReadFile
-    :: FilePath
-    -> FileSystem (Either SomeException ByteString)
-
-readFile
-  :: forall xs
-  . (Associate "fs" FileSystem xs
-  , Associate "fs_error" (EitherEff SomeException) xs)
-  => FilePath
-  -> Eff xs ByteString
-readFile fp = liftEff #fs (ReadFile fp)
-           >>= either (throwEff #fs_error) pure
-
-foo :: forall xs. Associate "fs" FileSystem xs => Eff xs (Either SomeException ByteString)
-foo = castEff (runEitherEff @ "fs_error" (readFile "foo") :: Eff '["fs" >: FileSystem] (Either SomeException ByteString))
diff --git a/extensible.cabal b/extensible.cabal
--- a/extensible.cabal
+++ b/extensible.cabal
@@ -1,5 +1,5 @@
 name:                extensible
-version:             0.4.7
+version:             0.4.7.1
 synopsis:            Extensible, efficient, optics-friendly data types and effects
 homepage:            https://github.com/fumieval/extensible
 bug-reports:         http://github.com/fumieval/extensible/issues
diff --git a/src/Data/Extensible/Dictionary.hs b/src/Data/Extensible/Dictionary.hs
--- a/src/Data/Extensible/Dictionary.hs
+++ b/src/Data/Extensible/Dictionary.hs
@@ -80,10 +80,6 @@
 newtype instance U.MVector s (h :* xs) = MV_Product (Comp (U.MVector s) h :* xs)
 newtype instance U.Vector (h :* xs) = V_Product (Comp U.Vector h :* xs)
 
-#define ENUM_EACH(expr) henumerateFor \
-  (Proxy :: Proxy (Instance1 U.Unbox h)) (Proxy :: Proxy (x ': xs)) \
-  ((>>) . (expr)) (return ())
-
 hlookupC :: Membership xs a -> Comp f g :* xs -> f (g a)
 hlookupC i = getComp . hlookup i
 
@@ -101,7 +97,7 @@
   basicUnsafeIndexM (V_Product v) i = hgenerateFor (Proxy :: Proxy (Instance1 U.Unbox h))
     $ \m -> G.basicUnsafeIndexM (hlookupC m v) i
   basicUnsafeCopy (MV_Product v) (V_Product w)
-    = ENUM_EACH(\i -> G.basicUnsafeCopy (hlookupC i v) (hlookupC i w))
+    = henumerateFor (Proxy :: Proxy (Instance1 U.Unbox h)) (Proxy :: Proxy (x ': xs)) ((>>) . \i -> G.basicUnsafeCopy (hlookupC i v) (hlookupC i w)) (return ())
 
 instance WrapForall U.Unbox h (x ': xs) => M.MVector U.MVector (h :* (x ': xs)) where
   basicLength (MV_Product v) = M.basicLength $ getComp $ hindex v here
@@ -116,20 +112,20 @@
     $ hgenerateFor (Proxy :: Proxy (Instance1 U.Unbox h))
     (const $ Comp <$> M.basicUnsafeNew n)
 #if MIN_VERSION_vector(0,11,0)
-  basicInitialize (MV_Product v) = ENUM_EACH(\i -> M.basicInitialize $ hlookupC i v)
+  basicInitialize (MV_Product v) = henumerateFor (Proxy :: Proxy (Instance1 U.Unbox h)) (Proxy :: Proxy (x ': xs)) ((>>) . \i -> M.basicInitialize $ hlookupC i v) (return ())
 #endif
   basicUnsafeReplicate n x = fmap MV_Product
     $ hgenerateFor (Proxy :: Proxy (Instance1 U.Unbox h))
     $ \m -> fmap Comp $ M.basicUnsafeReplicate n $ hlookup m x
   basicUnsafeRead (MV_Product v) i = hgenerateFor (Proxy :: Proxy (Instance1 U.Unbox h))
     (\m -> M.basicUnsafeRead (hlookupC m v) i)
-  basicUnsafeWrite (MV_Product v) i x = ENUM_EACH(\m -> M.basicUnsafeWrite (hlookupC m v) i (hlookup m x))
-  basicClear (MV_Product v) = ENUM_EACH(\i -> M.basicClear $ hlookupC i v)
-  basicSet (MV_Product v) x = ENUM_EACH(\i -> M.basicSet (hlookupC i v) (hlookup i x))
+  basicUnsafeWrite (MV_Product v) i x = henumerateFor (Proxy :: Proxy (Instance1 U.Unbox h)) (Proxy :: Proxy (x ': xs)) ((>>) . \m -> M.basicUnsafeWrite (hlookupC m v) i (hlookup m x)) (return ())
+  basicClear (MV_Product v) = henumerateFor (Proxy :: Proxy (Instance1 U.Unbox h)) (Proxy :: Proxy (x ': xs)) ((>>) . \i -> M.basicClear $ hlookupC i v) (return ())
+  basicSet (MV_Product v) x = henumerateFor (Proxy :: Proxy (Instance1 U.Unbox h)) (Proxy :: Proxy (x ': xs)) ((>>) . \i -> M.basicSet (hlookupC i v) (hlookup i x)) (return ())
   basicUnsafeCopy (MV_Product v1) (MV_Product v2)
-    = ENUM_EACH(\i -> M.basicUnsafeCopy (hlookupC i v1) (hlookupC i v2))
+    = henumerateFor (Proxy :: Proxy (Instance1 U.Unbox h)) (Proxy :: Proxy (x ': xs)) ((>>) . \i -> M.basicUnsafeCopy (hlookupC i v1) (hlookupC i v2)) (return ())
   basicUnsafeMove (MV_Product v1) (MV_Product v2)
-    = ENUM_EACH(\i -> M.basicUnsafeMove (hlookupC i v1) (hlookupC i v2))
+    = henumerateFor (Proxy :: Proxy (Instance1 U.Unbox h)) (Proxy :: Proxy (x ': xs)) ((>>) . \i -> M.basicUnsafeMove (hlookupC i v1) (hlookupC i v2)) (return ())
   basicUnsafeGrow (MV_Product v) n = fmap MV_Product
     $ hgenerateFor (Proxy :: Proxy (Instance1 U.Unbox h))
     $ \i -> Comp <$> M.basicUnsafeGrow (hlookupC i v) n
diff --git a/src/Data/Extensible/GetOpt.hs b/src/Data/Extensible/GetOpt.hs
--- a/src/Data/Extensible/GetOpt.hs
+++ b/src/Data/Extensible/GetOpt.hs
@@ -7,16 +7,24 @@
 --
 -- Maintainer  :  Fumiaki Kinoshita <fumiexcel@gmail.com>
 --
--- A wrapper for 'System.Console.GetOpt'
+-- A wrapper for 'System.Console.GetOpt'.
+--
+-- See also: <https://www.schoolofhaskell.com/user/fumieval/extensible/getopt-and-extensible-records GetOpt and extensible records - School of Haskell>
+--
 --------------------------------------------------------------------------------
 module Data.Extensible.GetOpt (OptionDescr(..)
   , OptDescr'
+  , getOptRecord
+  , withGetOpt
+  -- * Basic descriptors
+  , optFlag
+  , optLastArg
+  -- * More generic descriptors
   , optNoArg
   , optReqArg
   , optionNoArg
   , optionReqArg
-  , getOptRecord
-  , withGetOpt) where
+  , optionOptArg) where
 
 import Control.Monad.IO.Class
 import Data.Extensible.Class
@@ -61,6 +69,13 @@
     -> OptDescr' Int
 optNoArg = optionNoArg Identity
 
+-- | True when specified
+optFlag :: [Char] -- ^ short option
+    -> [String] -- ^ long option
+    -> String -- ^ explanation
+    -> OptDescr' Bool
+optFlag = optionNoArg (pure . (>0))
+
 optionNoArg :: (Int -> h a) -> [Char] -> [String] -> String -> OptionDescr h a
 optionNoArg f ss ls expl = OptionDescr f 0 $ Option ss ls (NoArg (+1)) expl
 
@@ -72,9 +87,21 @@
     -> OptDescr' [String]
 optReqArg = optionReqArg Identity
 
+-- | Takes the last argument when more than one is specified.
+optLastArg :: [Char] -- ^ short option
+    -> [String] -- ^ long option
+    -> String -- ^ placeholder
+    -> String -- ^ explanation
+    -> OptDescr' (Maybe String)
+optLastArg ss ls ph expl = OptionDescr pure Nothing $ Option ss ls (ReqArg (const . Just) ph) expl
+
 optionReqArg :: ([String] -> h a) -> [Char] -> [String] -> String -> String -> OptionDescr h a
 optionReqArg f ss ls ph expl = OptionDescr f [] $ Option ss ls (ReqArg (:) ph) expl
 
+optionOptArg :: ([Maybe String] -> h a) -> [Char] -> [String] -> String -> String -> OptionDescr h a
+optionOptArg f ss ls ph expl = OptionDescr f [] $ Option ss ls (OptArg (:) ph) expl
+
+-- | Parse option arguments.
 getOptRecord :: RecordOf (OptionDescr h) xs -- ^ a record of option descriptors
     -> [String] -- ^ arguments
     -> (RecordOf h xs, [String], [String], String -> String) -- ^ (result, remaining non-options, errors, usageInfo)
@@ -87,10 +114,13 @@
   result = hmap (\(Field (OptionDescr k x _)) -> Field (k x))
       $ foldl' (flip id) descs fs
 
--- | When there's an error, print it along with the usage info to stderr
+-- | An all-in-one utility function.
+-- When there's an error, print it along with the usage info to stderr
 -- and terminate with 'exitFailure'.
-withGetOpt :: MonadIO m => String -> RecordOf (OptionDescr h) xs
-  -> (RecordOf h xs -> [String] -> m a) -> m a
+withGetOpt :: MonadIO m => String -- ^ Non-option usage
+  -> RecordOf (OptionDescr h) xs -- ^ option desciptors
+  -> (RecordOf h xs -> [String] -> m a) -- ^ the result and non-option arguments
+  -> m a
 withGetOpt nonOptUsage descs k = getOptRecord descs <$> liftIO getArgs >>= \case
   (r, xs, [], _) -> k r xs
   (_, _, errs, usage) -> liftIO $ do
diff --git a/src/Data/Extensible/Internal.hs b/src/Data/Extensible/Internal.hs
--- a/src/Data/Extensible/Internal.hs
+++ b/src/Data/Extensible/Internal.hs
@@ -65,7 +65,6 @@
 import Data.Hashable
 import Data.Typeable
 import Language.Haskell.TH hiding (Pred)
-import Data.Bits
 import Data.Semigroup (Semigroup(..))
 import GHC.TypeLits
 
diff --git a/src/Data/Extensible/Record.hs b/src/Data/Extensible/Record.hs
--- a/src/Data/Extensible/Record.hs
+++ b/src/Data/Extensible/Record.hs
@@ -60,7 +60,6 @@
 #else
   TyConI (DataD _ _ vars [RecC conName vst] _) -> do
 #endif
-    rec <- newName "rec"
     let names = [x | (x, _, _) <- vst]
     newNames <- traverse (newName . nameBase) names
     let tvmap = [(tvName tv, VarT (mkName $ "p" ++ show i)) | (i, tv) <- zip [0 :: Int ..] vars]
