--------------------------------------------------------------------------------
--                              PUBLIC INTERFACE                              --
--------------------------------------------------------------------------------

-- mkopts ----------------------------------------------------------------------

{- | primary entry point for options generation

     @
       $( mkopts "getoptsx" (ArgSome 1 3) "integer"
                 [ "s|string\>str::String#string summary"
                 , "i|int|Int::Int\<4\>#integer summary\ndefault 4"
                 , "C\>incr::incr#increment summary\nincrement int longhelp"
                 , "decr|D::decr\<6\>#decrement summary\ndecrement int longhelp"
                 , "handle::filero\</etc/motd\>#read-only file\nauto-opened"
                 ]
        )

       main :: IO ()
       main = do
         (args, opts) <- getoptsx (return . (readType \"Int\" :: String -> Int))
         forM_ [ "ARGS: " ++ show args, "OPTS: "  ++ show opts ] putStrLn
         putStrLn $ "s: "    ++ show (opts ^. s)
         putStrLn $ "i: "    ++ show (opts ^. i)
         putStrLn $ "incr: " ++ show (opts ^. incr)
         putStrLn $ "decr: " ++ show (opts ^. decr)
     @

     Call this within a splice, providing the name of a fn to generate, along
     with defining parameters.  That function will be generated, returning
     parsed arguments and options, having eagerly/strictly parsed them (so that
     any relevant errors are found at this time).

     The option strings are compiled.  The syntax is:

     >  {optnames}(>{lensname})?::{type}(<{default})>?#{shorthelp}(\n{longhelp})?

     * optnames

       A list of option names, separated by @|@, to be used for invocation.

         * Each name may be single character, being invoked with @-c@, or
           multi-character, being invoked with @--chars@.
         * Each name may consist of some combination of letters, numbers, and
           hyphens (@-@).  The first (or only) character must alphanumeric.
         * Each name must be unique across the set of options.
         * Option names are case-sensitive; @c@ and @C@ are distinct option
           names.

       The option name list may not be empty.

   * lensname

       The name of the lens to target with this option.  The same naming rules
       apply as for optnames, with the following exceptions:

         * hyphens (@-@) are not permitted; underscores (@_@) are,
         * the name may begin with an underscore or an alphabetic character
           (note not a number).

       If a lensname is not given, then the first of the given option names is
       used.

         * any hyphens are replaced with underscores,
         * an option name with a leading digit is preceded in the lensname with
           an underscore.

       Each lensname must be unique both within the option set and be a unique
       function name within the compilation context.

       The lensname, whether explicit or implicitly 'inherited' from the option
       names, may not begin with a capital letter (because it becomes a function
       in code)

   * type

       The value type of the option.  This is the type of the value that is
       expected to be returned by the lens; internally, a different type
       (typically using an encapsulating monad, e.g., Maybe t).

       The available types are:

         * Standard haskell types, as an alphanumeric string.  Compound types
           (with spaces in the name) are not currently supported.  The following
           types have a natural default:

             * String - ""
             * Int    - 0

           For those that don't have a natural default, if no default is
           supplied in the option specification and the user doesn't invoke the
           given option; then an error will be generated at option parsing time
           - thus you effectively have mandatory options.

         * incr

           Takes no value on the cmdline; each invocation increases the option
           value.  Starting value is 0, or the default value if specified.  User
           sees an Int.

         * decr

           Takes no value on the cmdline; each invocation increases the option
           value.  Starting value is 0, or the default value if specified.  User
           sees an Int.

         * filero

           Takes the name of a file as cmdline argument; opens the file RO, and
           returns a handle to the file.  Generates an error at options-parsing
           runtime if no user value is supplied, and there is no default.

         * ?t or Maybe t

           This is like t, except that the value is wrapped in a Maybe; if no
           value is provided on the command line is provided, you get Nothing.
           Compilation will fail if you provide a default value
           (with <default>); at that point, the use of Maybe doesn't make a
           whole lot of sense (since you would be guaranteed a Just something).
           If you really, really want a Maybe type with a default, use an
           explicit Maybe.type (which will also mean that you can specify
           "Nothing" as an option value; but conversely that you'll also need to
           specify "Just x" explitly as an option value).

         * [t]

   * default

     The value to return to the caller if the option is never invoked by the
     user.  The string provided is given to read.

   * shorthelp

     short summary used with --help; pref < 50 chars

   * longhelp

     long help used with --help=optname
-}

mkopts :: String                           -- ^ name of the getopts fn to
                                           --   create, e.g., "optCfg"
       -> ArgArity                         -- ^ arity of arguments
       -> String                           -- ^ arg type (for help text)
       -- we use just a big string to allow for optionality of bits
       -> [String]                         {- ^ opt configurations;
                                                config string, default value,
                                                long descripton
                                            -}
       -> DecsQ

mkopts getoptName arity argtype optcfgs = do
  {- mkopts "getoptsx" (ArgSome 1 3) "integer"
           [ "s|string::String#summary"
           , "incr|C::incr#increment summary\nincrement int longhelp"
           , "handle::filero</etc/motd>#read-only file\nauto-opened"
           ]

     generates something like

     data Getoptsx__ = Getoptsx__ { _s__      :: Maybe String
                                  , _incr__   :: Int
                                  , _handle__ :: Maybe FilePath
                                  }
       deriving Show
     instance Default Getoptsx__ where def = Getoptsx__ Nothing 0 Nothing

     s___ :: Lens' Getoptsx__ (Maybe String)
     s___      a b = fmap asn (a $ (_s___ b))
       where asn x = b { _s___      = x }

     incr___ :: Lens' Getoptsx_ Int
     incr___   a b = fmap asn (a $ (_incr___ b))
       where asn x = b {_incr___    = x }

     handle___ :: Lens' Getopts__ (Maybe FilePath)
     handle___ a b = fmap asn (a $ ( _handle___ b))
       where asn x = b { _handle___ = x }

     data Getoptsx = Getoptsx { _s :: String
                              , _incr :: Int
                              , _handle :: Handle
                              }
       deriving Show

     s :: Lens' Getoptsx String
     s      a b = fmap asn (a $ (_s b))      where asn x = b { _s      = x }

     incr :: Lens' Getoptsx Int
     incr   a b = fmap asn (a $ (_incr b))   where asn x = b { _incr   = x }

     handle :: Lens' Getoptsx Handle
     handle a b = fmap asn (a $ (_handle b)) where asn x = b { _handle = x }

     getoptsx_ :: [Option Getoptsx_]
     getoptsx_ = [ mkOpt "s" ["string"] (setval parseAs "String" s___)
                         "string summary" "" "Maybe String" "\"\""
                 , mkOpt "C" ["incr"]   (setvalc incr___)
                         "increment summary" "increment int longhelp" "Int" "0"

                 , mkOpt ""  ["handle"] (setval return handle___)
                         "read-only file" "auto-opened"
                         "Maybe FilePath" "GHC.Base.id \"/etc/motd\"",

                 , mkOpt "" ["help"] helpme (def { arg_arity = ArgSome 1 3
                                                 , argtype  = "integer" })
                         "this help" "Provide help text..." "" ""
                 ]

      getoptsx_effect :: Getoptsx__ -> IO (Either [NFException] Getoptsx)
      getoptsx_effect pclv = do
        ((string_x', incr_x', handle_x'), exs) <- runWriterT $ do
                string_x    <- tryWriteF $
                                 return (((fromMaybe "") . (view s___)) pclv);
                incr_x      <- tryWriteF $ return (view incr___ pclv)
                handle_x    <- tryWriteF $
                                 openFileRO (((fromMaybe "/etc/motd")
                                              . (view handle___)) pclv)
                return (string_x, incr_x, handle_x)
        return $ if null exs
                 then Right $ Getoptsx (fromJust string_x')
                                       (fromJust incr_x')
                                       (fromJust handle_x')
                 else Left exs

    getoptsx :: (NFData a, Show a) => (String -> IO a) -> IO ([a], Getoptsx)
    getoptsx = (t2apply (checkEx . getoptsx_effect))
               . (getopts getoptsx_ (ArgSome 1 3) "integer")

  -}

  let optdescs :: [OptDesc]
      optdescs = fmap read optcfgs

      -- assign a list of options (returned by mkOpt) to a name
      -- (getoptsx_ :: [Option Getoptsx_]; getoptsx_ = [ mkOpt ... ] above)
      mkopts_ts :: Type
      mkopts_ts = AppT ListT (AppT (ConT ''Option) (pclv_typename getoptName))

      -- create a record to hold PCLVs.  This is created in one pass; and when
      -- it comes to creating the OVs record, defaults are inserted as necessary
      -- and IO is performed to produce the user-visible opts record
      -- (data Getoptsx__ = Getoptsx__ { ... } above)
      precord :: DecsQ
      precord = mkLensedRecordDef (pclv_typename getoptName)
                                  (fmap precordDefFields optdescs)
                                  [''Show]

      -- create a record to hold final values to pass back to the user;
      -- (data Getoptsx = Getoptsx { ... } above)
      record :: DecsQ
      record = mkLensedRecord (ov_typename getoptName)
                              (fmap recordFields optdescs)
                              [''Show]

  opts :: [Exp] <- sequence $ fmap mkopt optdescs ++ [ helpmeQ arity argtype ]
  -- assign a list of mkOpt calls to the chosen var
  -- (getoptsx_ :: [Option Getoptsx_];getoptsx_ = [ mkOpt ... ] above)
  let asgn_mkopts :: DecsQ
      asgn_mkopts = return [ -- getoptsx_ :: [Option Getoptsx_]
                             SigD (cfg_name getoptName) mkopts_ts
                           , -- getoptsx_ = [ mkOpt ... ]
                             assignN (cfg_name getoptName) (ListE opts)
                           ]


  concatM [ precord      -- (data Getoptsx__ = Getoptsx__ { ... } above)
          , record       -- (data Getoptsx = Getoptsx { ... }     above)
          , asgn_mkopts  -- (getoptsx_ ...                        above)
            -- (getoptsx_effect :: Getoptsx__ ->
            --                                IO (Either [NFException] Getoptsx)
            --  getoptsx_effect pclv = pclv -> do { ... }
            --  getoptsx :: (NFData a, Show a) => (String -> IO a)
            --                                 -> IO ([a], Getoptsx)
            --  getoptsx = (t2apply (checkEx . getoptsx_effect))
            --             . (getopts getoptsx_ (ArgSome 1 3) "integer")
            --  above)
          , mkGetoptTH optdescs getoptName arity argtype
          ]

--------------------------------------------------------------------------------
--                             INTERNAL FUNCTIONS                             --
--------------------------------------------------------------------------------

-- mkGetoptTH ------------------------------------------------------------------

{- | generate effector & getopts_th fn

     (getoptsx_effect :: Getoptsx__ -> IO (Either [NFException] Getoptsx)
      getoptsx_effect pclv = do
        ((string_x', incr_x', handle_x'), exs) <- runWriterT $ do
                string_x    <- tryWriteF $
                                 return (((fromMaybe "") . (view s___)) pclv);
                incr_x      <- tryWriteF $ return (view incr___ pclv)
                handle_x    <- tryWriteF $
                                 openFileRO (((fromMaybe "/etc/motd")
                                              . (view handle___)) pclv)
                return (string_x, incr_x, handle_x)
        return $ if null exs
                 then Right $ Getoptsx (fromJust string_x')
                                       (fromJust incr_x')
                                       (fromJust handle_x')
                 else Left exs

      getoptsx :: (NFData a, Show a) => (String -> IO a)
                                     -> IO ([a], Getoptsx)

      getoptsx = (t2apply (checkEx . getoptsx_effect))
                 . (getopts getoptsx_ (ArgSome 1 3) "integer")
      above)
 -}
mkopts :: String                           -- ^ name of the getopts fn to
                                           --   create, e.g., "optCfg"
       -> ArgArity                         -- ^ arity of arguments
       -> String                           -- ^ arg type (for help text)
       -- we use just a big string to allow for optionality of bits
       -> [String]                         {- ^ opt configurations;
                                                config string, default value,
                                                long descripton
                                            -}
       -> DecsQ
mkopts getoptName arity argtype optcfgs = do
  {- mkopts "getoptsx" (ArgSome 1 3) "integer"
           [ "s|string::String#summary"
           , "incr|C::incr#increment summary\nincrement int longhelp"
           , "handle::filero</etc/motd>#read-only file\nauto-opened"
           ]

     generates something like

     data Getoptsx__ = Getoptsx__ { _s__      :: Maybe String
                                  , _incr__   :: Int
                                  , _handle__ :: Maybe FilePath
                                  }
       deriving Show
     instance Default Getoptsx__ where def = Getoptsx__ Nothing 0 Nothing

     s___ :: Lens' Getoptsx__ (Maybe String)
     s___      a b = fmap asn (a $ (_s___ b))
       where asn x = b { _s___      = x }

     incr___ :: Lens' Getoptsx_ Int
     incr___   a b = fmap asn (a $ (_incr___ b))
       where asn x = b {_incr___    = x }

     handle___ :: Lens' Getopts__ (Maybe FilePath)
     handle___ a b = fmap asn (a $ ( _handle___ b))
       where asn x = b { _handle___ = x }

     data Getoptsx = Getoptsx { _s :: String
                              , _incr :: Int
                              , _handle :: Handle
                              }
       deriving Show

     s :: Lens' Getoptsx String
     s      a b = fmap asn (a $ (_s b))      where asn x = b { _s      = x }

     incr :: Lens' Getoptsx Int
     incr   a b = fmap asn (a $ (_incr b))   where asn x = b { _incr   = x }

     handle :: Lens' Getoptsx Handle
     handle a b = fmap asn (a $ (_handle b)) where asn x = b { _handle = x }

     getoptsx_ :: [Option Getoptsx_]
     getoptsx_ = [ mkOpt "s" ["string"] (setval parseAs "String" s___)
                         "string summary" "" "Maybe String" "\"\""
                 , mkOpt "C" ["incr"]   (setvalc incr___)
                         "increment summary" "increment int longhelp" "Int" "0"

                 , mkOpt ""  ["handle"] (setval return handle___)
                         "read-only file" "auto-opened"
                         "Maybe FilePath" "GHC.Base.id \"/etc/motd\"",

                 , mkOpt "" ["help"] helpme (def { arg_arity = ArgSome 1 3
                                                 , argtype  = "integer" })
                         "this help" "Provide help text..." "" ""
                 ]

      getoptsx_effect :: Getoptsx__ -> IO (Either [NFException] Getoptsx)
      getoptsx_effect pclv = do
        ((string_x', incr_x', handle_x'), exs) <- runWriterT $ do
                string_x    <- tryWriteF $
                                 return (((fromMaybe "") . (view s___)) pclv);
                incr_x      <- tryWriteF $ return (view incr___ pclv)
                handle_x    <- tryWriteF $
                                 openFileRO (((fromMaybe "/etc/motd")
                                              . (view handle___)) pclv)
                return (string_x, incr_x, handle_x)
        return $ if null exs
                 then Right $ Getoptsx (fromJust string_x')
                                       (fromJust incr_x')
                                       (fromJust handle_x')
                 else Left exs

    getoptsx :: (NFData a, Show a) => (String -> IO a) -> IO ([a], Getoptsx)
    getoptsx = (t2apply (checkEx . getoptsx_effect))
               . (getopts getoptsx_ (ArgSome 1 3) "integer")

  -}

  let optdescs :: [OptDesc]
      optdescs = fmap read optcfgs

      -- assign a list of options (returned by mkOpt) to a name
      -- (getoptsx_ :: [Option Getoptsx_]; getoptsx_ = [ mkOpt ... ] above)
      mkopts_ts :: Type
      mkopts_ts = AppT ListT (AppT (ConT ''Option) (pclv_typename getoptName))

      -- create a record to hold PCLVs.  This is created in one pass; and when
      -- it comes to creating the OVs record, defaults are inserted as necessary
      -- and IO is performed to produce the user-visible opts record
      -- (data Getoptsx__ = Getoptsx__ { ... } above)
      precord :: DecsQ
      precord = mkLensedRecordDef (pclv_typename getoptName)
                                  (fmap precordDefFields optdescs)
                                  [''Show]

      -- create a record to hold final values to pass back to the user;
      -- (data Getoptsx = Getoptsx { ... } above)
      record :: DecsQ
      record = mkLensedRecord (ov_typename getoptName)
                              (fmap recordFields optdescs)
                              [''Show]

  opts :: [Exp] <- sequence $ fmap mkopt optdescs ++ [ helpmeQ arity argtype ]
  -- assign a list of mkOpt calls to the chosen var
  -- (getoptsx_ :: [Option Getoptsx_];getoptsx_ = [ mkOpt ... ] above)
  let asgn_mkopts :: DecsQ
      asgn_mkopts = return [ -- getoptsx_ :: [Option Getoptsx_]
                             SigD (cfg_name getoptName) mkopts_ts
                           , -- getoptsx_ = [ mkOpt ... ]
                             assignN (cfg_name getoptName) (ListE opts)
                           ]


  concatM [ precord      -- (data Getoptsx__ = Getoptsx__ { ... } above)
          , record       -- (data Getoptsx = Getoptsx { ... }     above)
          , asgn_mkopts  -- (getoptsx_ ...                        above)
            -- (getoptsx_effect :: Getoptsx__ ->
            --                                IO (Either [NFException] Getoptsx)
            --  getoptsx_effect pclv = pclv -> do { ... }
            --  getoptsx :: (NFData a, Show a) => (String -> IO a)
            --                                 -> IO ([a], Getoptsx)
            --  getoptsx = (t2apply (checkEx . getoptsx_effect))
            --             . (getopts getoptsx_ (ArgSome 1 3) "integer")
            --  above)
          , mkGetoptTH optdescs getoptName arity argtype
          ]

--------------------------------------------------------------------------------
--                             INTERNAL FUNCTIONS                             --
--------------------------------------------------------------------------------

-- mkGetoptTH ------------------------------------------------------------------

{- | generate effector & getopts_th fn

     (getoptsx_effect :: Getoptsx__ -> IO (Either [NFException] Getoptsx)
      getoptsx_effect pclv = do
        ((string_x', incr_x', handle_x'), exs) <- runWriterT $ do
                string_x    <- tryWriteF $
                                 return (((fromMaybe "") . (view s___)) pclv);
                incr_x      <- tryWriteF $ return (view incr___ pclv)
                handle_x    <- tryWriteF $
                                 openFileRO (((fromMaybe "/etc/motd")
                                              . (view handle___)) pclv)
                return (string_x, incr_x, handle_x)
        return $ if null exs
                 then Right $ Getoptsx (fromJust string_x')
                                       (fromJust incr_x')
                                       (fromJust handle_x')
                 else Left exs

      getoptsx :: (NFData a, Show a) => (String -> IO a)
                                     -> IO ([a], Getoptsx)

      getoptsx = (t2apply (checkEx . getoptsx_effect))
                 . (getopts getoptsx_ (ArgSome 1 3) "integer")
      above)
 -}
mkopts getoptName arity argtype optcfgs = do
  {- mkopts "getoptsx" (ArgSome 1 3) "integer"
           [ "s|string::String#summary"
           , "incr|C::incr#increment summary\nincrement int longhelp"
           , "handle::filero</etc/motd>#read-only file\nauto-opened"
           ]

     generates something like

     data Getoptsx__ = Getoptsx__ { _s__      :: Maybe String
                                  , _incr__   :: Int
                                  , _handle__ :: Maybe FilePath
                                  }
       deriving Show
     instance Default Getoptsx__ where def = Getoptsx__ Nothing 0 Nothing

     s___ :: Lens' Getoptsx__ (Maybe String)
     s___      a b = fmap asn (a $ (_s___ b))
       where asn x = b { _s___      = x }

     incr___ :: Lens' Getoptsx_ Int
     incr___   a b = fmap asn (a $ (_incr___ b))
       where asn x = b {_incr___    = x }

     handle___ :: Lens' Getopts__ (Maybe FilePath)
     handle___ a b = fmap asn (a $ ( _handle___ b))
       where asn x = b { _handle___ = x }

     data Getoptsx = Getoptsx { _s :: String
                              , _incr :: Int
                              , _handle :: Handle
                              }
       deriving Show

     s :: Lens' Getoptsx String
     s      a b = fmap asn (a $ (_s b))      where asn x = b { _s      = x }

     incr :: Lens' Getoptsx Int
     incr   a b = fmap asn (a $ (_incr b))   where asn x = b { _incr   = x }

     handle :: Lens' Getoptsx Handle
     handle a b = fmap asn (a $ (_handle b)) where asn x = b { _handle = x }

     getoptsx_ :: [Option Getoptsx_]
     getoptsx_ = [ mkOpt "s" ["string"] (setval parseAs "String" s___)
                         "string summary" "" "Maybe String" "\"\""
                 , mkOpt "C" ["incr"]   (setvalc incr___)
                         "increment summary" "increment int longhelp" "Int" "0"

                 , mkOpt ""  ["handle"] (setval return handle___)
                         "read-only file" "auto-opened"
                         "Maybe FilePath" "GHC.Base.id \"/etc/motd\"",

                 , mkOpt "" ["help"] helpme (def { arg_arity = ArgSome 1 3
                                                 , argtype  = "integer" })
                         "this help" "Provide help text..." "" ""
                 ]

      getoptsx_effect :: Getoptsx__ -> IO (Either [NFException] Getoptsx)
      getoptsx_effect pclv = do
        ((string_x', incr_x', handle_x'), exs) <- runWriterT $ do
                string_x    <- tryWriteF $
                                 return (((fromMaybe "") . (view s___)) pclv);
                incr_x      <- tryWriteF $ return (view incr___ pclv)
                handle_x    <- tryWriteF $
                                 openFileRO (((fromMaybe "/etc/motd")
                                              . (view handle___)) pclv)
                return (string_x, incr_x, handle_x)
        return $ if null exs
                 then Right $ Getoptsx (fromJust string_x')
                                       (fromJust incr_x')
                                       (fromJust handle_x')
                 else Left exs

    getoptsx :: (NFData a, Show a) => (String -> IO a) -> IO ([a], Getoptsx)
    getoptsx = (t2apply (checkEx . getoptsx_effect))
               . (getopts getoptsx_ (ArgSome 1 3) "integer")

  -}

  let optdescs :: [OptDesc]
      optdescs = fmap read optcfgs

      -- assign a list of options (returned by mkOpt) to a name
      -- (getoptsx_ :: [Option Getoptsx_]; getoptsx_ = [ mkOpt ... ] above)
      mkopts_ts :: Type
      mkopts_ts = AppT ListT (AppT (ConT ''Option) (pclv_typename getoptName))

      -- create a record to hold PCLVs.  This is created in one pass; and when
      -- it comes to creating the OVs record, defaults are inserted as necessary
      -- and IO is performed to produce the user-visible opts record
      -- (data Getoptsx__ = Getoptsx__ { ... } above)
      precord :: DecsQ
      precord = mkLensedRecordDef (pclv_typename getoptName)
                                  (fmap precordDefFields optdescs)
                                  [''Show]

      -- create a record to hold final values to pass back to the user;
      -- (data Getoptsx = Getoptsx { ... } above)
      record :: DecsQ
      record = mkLensedRecord (ov_typename getoptName)
                              (fmap recordFields optdescs)
                              [''Show]

  opts :: [Exp] <- sequence $ fmap mkopt optdescs ++ [ helpmeQ arity argtype ]
  -- assign a list of mkOpt calls to the chosen var
  -- (getoptsx_ :: [Option Getoptsx_];getoptsx_ = [ mkOpt ... ] above)
  let asgn_mkopts :: DecsQ
      asgn_mkopts = return [ -- getoptsx_ :: [Option Getoptsx_]
                             SigD (cfg_name getoptName) mkopts_ts
                           , -- getoptsx_ = [ mkOpt ... ]
                             assignN (cfg_name getoptName) (ListE opts)
                           ]


  concatM [ precord      -- (data Getoptsx__ = Getoptsx__ { ... } above)
          , record       -- (data Getoptsx = Getoptsx { ... }     above)
          , asgn_mkopts  -- (getoptsx_ ...                        above)
            -- (getoptsx_effect :: Getoptsx__ ->
            --                                IO (Either [NFException] Getoptsx)
            --  getoptsx_effect pclv = pclv -> do { ... }
            --  getoptsx :: (NFData a, Show a) => (String -> IO a)
            --                                 -> IO ([a], Getoptsx)
            --  getoptsx = (t2apply (checkEx . getoptsx_effect))
            --             . (getopts getoptsx_ (ArgSome 1 3) "integer")
            --  above)
          , mkGetoptTH optdescs getoptName arity argtype
          ]

--------------------------------------------------------------------------------
--                             INTERNAL FUNCTIONS                             --
--------------------------------------------------------------------------------

-- mkGetoptTH ------------------------------------------------------------------

{- | generate effector & getopts_th fn

     (getoptsx_effect :: Getoptsx__ -> IO (Either [NFException] Getoptsx)
      getoptsx_effect pclv = do
        ((string_x', incr_x', handle_x'), exs) <- runWriterT $ do
                string_x    <- tryWriteF $
                                 return (((fromMaybe "") . (view s___)) pclv);
                incr_x      <- tryWriteF $ return (view incr___ pclv)
                handle_x    <- tryWriteF $
                                 openFileRO (((fromMaybe "/etc/motd")
                                              . (view handle___)) pclv)
                return (string_x, incr_x, handle_x)
        return $ if null exs
                 then Right $ Getoptsx (fromJust string_x')
                                       (fromJust incr_x')
                                       (fromJust handle_x')
                 else Left exs

      getoptsx :: (NFData a, Show a) => (String -> IO a)
                                     -> IO ([a], Getoptsx)

      getoptsx = (t2apply (checkEx . getoptsx_effect))
                 . (getopts getoptsx_ (ArgSome 1 3) "integer")
      above)
 -}