I'm trying to build a CLI food journal app.
And this is the data type I want the user input to be parsed in.
data JournalCommand =
JournalSearch Query DataTypes Ingridents BrandOwnder PageNumber
| JournalReport Query DataTypes Ingridents BrandOwnder PageNumber ResultNumber
| JournalDisplay FromDate ToDate ResultNumber
| JournalStoreSearch Query DataTypes Ingridents BrandOwnder PageNumber ResultNumber StoreFlag
| JournalStoreCustom CustomEntry OnDate StoreFlag
| JournalDelete FromDate ToDate ResultNumber
| JournalEdit CustomEntry ResultNumber
deriving (Show, Eq)
and because there's a lot of overlap I have a total of 8 functions with Parser a
type.
Functions like these
-- | Search Query
aQueryParser :: Parser String
aQueryParser = strOption
( long "search"
<> short 's'
<> help "Search for a term in the database"
)
The idea if to ultimately have a function like this
runJournal :: JournalCommand -> MT SomeError IO ()
runJournal = \case
JournalSearch q d i b p
-> runSearch q d i b p
JournalReport q d i b p r
-> runSearchAndReport q d i b p r
...
...
where MT
is some monad transformer that can handle error
+ IO
. Not sure yet.
The question is: How do I setup the parseArgs
function
parseArgs :: IO JournalCommand
parseArgs = execParser ...
and parser
function
parser :: Parser JournalCommand
parser = ...
so that I'd be able to parse user input into JournalCommand
and then return the data to relevant functions.
I know I can fmap
a data type like this
data JournalDisplay { jdFromDate :: UTCTime
, jdToDate :: UTCTime
, jdResultNumber :: Maybe Int
}
as
JournalDisplay
<$>
fromDateParser
<*>
toDateParser
<*>
optional resultNumberParser
But I'm not sure how to go about doing that with my original data structure.
I think I need to have a list like this [Mod CommandFields JournalCommand]
which I may be able to pass into subparser
function by concatenating the Mod
list. I'm not completely sure.