使用 optparse-applicative 制作一个 'optional' 解析器并为递归数据类型构造值

Making an 'optional' parser using optparse-applicative and constructing value for recursive data type

我有一个叫做EntrySearchableInfo的数据类型是这样写的

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

基本上表示在 'search' 上下文中有意义的事物。

我想用这种类型写一个函数

entrySearchableInfoParser :: Parser (Either String EntrySearchableInfo)

(我认为)这将是我已经编写的几个原始 Parser <Type> 函数的组合

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 = ...
...

所以我有两个问题:

  1. 如何组合这些解析器来制作 entrySearchableInfoParser 函数。

  2. EntrySearchableInfo 类型是更大的 Entry 类型的一部分,定义如下

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

我已经有一个类型为

的函数
entryAdd :: Parser (Either String Entry) 

使用Add构造Entry

但我不确定如何使用 ReplaceentrySearchableInfoParserentryAdd.

来制作 Entry 类型

所以结合这些解析器比我想象的要简单得多。

我只需要使用 <|>

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

并使用 ReplaceentrySearchableInfoParser 以及 entryAdd 构建 Entry 类型也是如此。

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

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

现在完美运行了!