使用 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 = ...
...
所以我有两个问题:
如何组合这些解析器来制作 entrySearchableInfoParser
函数。
EntrySearchableInfo
类型是更大的 Entry
类型的一部分,定义如下
data Entry
= Add EntryDate EntryInfo EntryTag EntryNote EntryId
| Replace EntrySearchableInfo Entry
| ...
...
我已经有一个类型为
的函数
entryAdd :: Parser (Either String Entry)
使用Add
构造Entry
。
但我不确定如何使用 Replace
与 entrySearchableInfoParser
和 entryAdd
.
来制作 Entry
类型
所以结合这些解析器比我想象的要简单得多。
我只需要使用 <|>
entrySearchableInfoParser :: Parser (Either String EntrySearchableInfo)
entrySearchableInfoParser =
searchableEntryDateParser
<|> searchableEntryTagParser
<|> searchableEntryNameParser
<|> searchableEntryDescriptionParser
<|> searchableEntryIdParser
并使用 Replace
和 entrySearchableInfoParser
以及 entryAdd
构建 Entry
类型也是如此。
entryAdd :: Parser (Either String Entry)
entryAdd = ...
entryReplace :: Parser (Either String Entry)
entryReplace = liftA2 Edit <$> entrySearchableInfoParser <*> entryAdd
现在完美运行了!
我有一个叫做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 = ...
...
所以我有两个问题:
如何组合这些解析器来制作
entrySearchableInfoParser
函数。EntrySearchableInfo
类型是更大的Entry
类型的一部分,定义如下
data Entry
= Add EntryDate EntryInfo EntryTag EntryNote EntryId
| Replace EntrySearchableInfo Entry
| ...
...
我已经有一个类型为
的函数entryAdd :: Parser (Either String Entry)
使用Add
构造Entry
。
但我不确定如何使用 Replace
与 entrySearchableInfoParser
和 entryAdd
.
Entry
类型
所以结合这些解析器比我想象的要简单得多。
我只需要使用 <|>
entrySearchableInfoParser :: Parser (Either String EntrySearchableInfo)
entrySearchableInfoParser =
searchableEntryDateParser
<|> searchableEntryTagParser
<|> searchableEntryNameParser
<|> searchableEntryDescriptionParser
<|> searchableEntryIdParser
并使用 Replace
和 entrySearchableInfoParser
以及 entryAdd
构建 Entry
类型也是如此。
entryAdd :: Parser (Either String Entry)
entryAdd = ...
entryReplace :: Parser (Either String Entry)
entryReplace = liftA2 Edit <$> entrySearchableInfoParser <*> entryAdd
现在完美运行了!