0

I have a data type called EntrySearchableInfo written like this

type EntryDate = UTCTime -- From Data.Time

type EntryTag = Tag -- String

type EntryName = Name -- String

type EntryDescription = Description -- String

type EntryId = Int
data EntrySearchableInfo
  = SearchableEntryDate EntryDate
  | SearchableEntryTag EntryTag
  | SearchableEntryName EntryName
  | SearchableEntryDescription EntryDescription
  | SearchableEntryId EntryId

Basically represents things that make sense in 'search' context.

I want to write a function with this type

entrySearchableInfoParser :: Parser (Either String EntrySearchableInfo)

which (I think) will be a combination of several primitive Parser <Type> functions I have already written

entryDateParser :: Parser (Either String UTCTime)
entryDateParser = parseStringToUTCTime <$> strOption
  (long "date" <> short 'd' <> metavar "DATE" <> help entryDateParserHelp)

searchableEntryDateParser :: Parser (Either String EntrySearchableInfo)
searchableEntryDateParser = SearchableEntryDate <$$> entryDateParser -- <$$> is just (fmap . fmap)

searchableEntryTagParser :: Parser (Either String EntrySearchableInfo)
searchableEntryTagParser = ...
...

So I have two questions:

  1. How do I combine those parsers to make entrySearchableInfoParser functions.

  2. EntrySearchableInfo type is a part of a larger Entry type defined like this

data Entry
    = Add EntryDate EntryInfo EntryTag EntryNote EntryId
    | Replace EntrySearchableInfo Entry
    | ...
    ...

I already have a function with type

entryAdd :: Parser (Either String Entry) 

which constructs Entry using Add.

But I'm not sure how to make Entry type using Replace with entrySearchableInfoParser and entryAdd.

atis
  • 881
  • 5
  • 22
  • You know that your `EntrySearchableInfo` type can only have 5 different values? – talex Mar 03 '20 at 07:30
  • Yeah I do, idea is if the user inputs any 'searchable' thing, `entrySearchableInfoParser` should construct a `Parser (Either String EntrySearchableInfo)` type. Am I missing something here? – atis Mar 03 '20 at 07:37
  • I mean it won't contain value of tag, only the fact it is tag. – talex Mar 03 '20 at 07:49
  • @talex You're right! I completely missed that. Should be fixed now. – atis Mar 03 '20 at 08:13

1 Answers1

0

So combining those parsers were a lot simpler than I imagined.

I just had to use <|>

entrySearchableInfoParser :: Parser (Either String EntrySearchableInfo)
entrySearchableInfoParser =
  searchableEntryDateParser
    <|> searchableEntryTagParser
    <|> searchableEntryNameParser
    <|> searchableEntryDescriptionParser
    <|> searchableEntryIdParser

and constructing Entry type using Replace with entrySearchableInfoParser and entryAdd was too.

entryAdd :: Parser (Either String Entry)
entryAdd = ...

entryReplace :: Parser (Either String Entry)
entryReplace = liftA2 Edit <$> entrySearchableInfoParser <*> entryAdd

Now it works perfectly!

atis
  • 881
  • 5
  • 22