Your question turned out to be more complicated than you think. Current optparse-applicative API is not supposed to be used with such cases. So you probably may want to change the way you handle CLI arguments or switch to another CLI parsing library. But I will describe most closest way of achieving your goal.

First, you need to read other two SO questions:

1. How to parse Maybe with optparse-applicative

2. Is it possible to have a optparse-applicative option with several parameters?

From first question you know how to parse optional arguments using optional function. From second you learn some problems with parsing multiple arguments. So I will write here several approaches how you can workaround this problem.

1. Naive and ugly

You can represent pair of strings as pair of String type and use just naive show of this pair. Here is code:

mainParser :: Parser Arguments mainParser = Arguments <$> switch (long "someflag" <> help "Some argument flag") <*> optional (uncurry SubArguments <$> (option auto $ long "subarguments" <> help "some desc")) getArguments :: IO Arguments getArguments = do (res, ()) <- simpleOptions "main example" "" "desc" mainParser empty return res main :: IO () main = getArguments >>= print

Here is result in ghci :

ghci> :run main --someflag --subarguments "(\"a\",\"b\")" Arguments True (Just (SubArguments "a" "b"))

2. Less naive

From answer to second question you should learn how pass multiple arguments inside one string. Here is code for parsing:

subArgParser :: ReadM SubArguments subArgParser = do input <- str -- no error checking, don't actually do this let [a,b] = words input pure $ SubArguments a b mainParser :: Parser Arguments mainParser = Arguments <$> switch (long "someflag" <> help "Some argument flag") <*> optional (option subArgParser $ long "subarguments" <> help "some desc")

And here is ghci output:

ghci> :run main --someflag --subarguments "x yyy" Arguments True (Just (SubArguments "x" "yyy"))