我似乎经常遇到将关键字直接映射到数据类型的情况,我如下解决了它。它很快就会失控,因为您必须重复字符串值。
有没有更紧凑的方式来表达这一点?
import Text.ParserCombinators.Parsec
data Keyword = Apple | Banana | Cantaloupe
parseKeyword :: Parser Keyword
parseKeyword = ( string "apple"
<|> string "banana"
<|> string "cantaloupe"
) >>= return . strToKeyword
where strToKeyword str = case str of
"apple" -> Apple
"banana" -> Banana
"cantaloupe" -> Cantaloupe
编辑:
作为后续问题,因为这似乎太容易了。紧凑的解决方案如何与
try
一起使用?例如。
import Text.ParserCombinators.Parsec
data Keyword = Apple | Apricot | Banana | Cantaloupe
parseKeyword :: Parser Keyword
parseKeyword = ( try (string "apple")
<|> string "apricot"
<|> string "banana"
<|> string "cantaloupe"
) >>= return . strToKeyword
where strToKeyword str = case str of
"apple" -> Apple
"apricot" -> Apricot
"banana" -> Banana
"cantaloupe" -> Cantaloupe
最佳答案
我不确定这是一个非常优雅的解决方案,但是如果您派生更多类型类:
data Keyword = Apple | Banana | Cantaloupe deriving (Eq, Read, Show, Enum, Bounded)
您可以突然获得所有值:
ghci> [minBound..maxBound] :: [Keyword]
[Apple,Banana,Cantaloupe]
对于任何特定的值,我们可以解析它然后返回值:
parseEnumValue :: (Show a) => a -> Parser a
parseEnumValue val = string (map toLower $ show val) >> return val
然后我们可以结合这些来解析它的任何值:
parseEnum :: (Show a, Enum a, Bounded a) => Parser a
parseEnum = choice $ map parseEnumValue [minBound..maxBound]
试试看:
ghci> parseTest (parseEnum :: Parser Keyword) "cantaloupe"
Cantaloupe
ghci> parseTest (parseEnum :: Parser Keyword) "orange"
parse error at (line 1, column 1):
unexpected "o"
expecting "apple", "banana" or "cantaloupe"
关于haskell - 使用 Parsec 将字符串映射到数据类型的紧凑方法,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25215184/