一般来说,我对 Haskell 和函数式编程还是很陌生,所以我正在用 Parsec 编写一个小程序来解析 JSON 并漂亮地打印它作为学习基本概念的一种手段。这是我到目前为止所拥有的:
import Text.Parsec
import Text.Parsec.String
data JValue = JString String
| JNumber Double
| JBool Bool
| JNull
| JObject [(String, JValue)]
| JArray [JValue]
deriving (Eq, Ord, Show)
parseJString, parseJNumber, parseJBool, parseJNull :: Parser JValue
parseJString = do
str <- between (char '"') (char '"') (many (noneOf "\""))
return . JString $ str
parseJNumber = do
num <- many digit
return . JNumber . read $ num
parseJBool = do
val <- string "true" <|> string "false"
case val of
"true" -> return (JBool True)
"false" -> return (JBool False)
parseJNull = string "null" >> return JNull
parseJValue :: Parser JValue
parseJValue = parseJString
<|> parseJNumber
<|> parseJBool
<|> parseJNull
现在,我假设这些数字是整数。单独地,parseJString
, parseJNumber
, parseJBool
, 和parseJNull
在 ghci 中按预期工作。此外,parseJValue
正确解析字符串和数字。
ghci> parse parseJString "test" "\"test input\""
Right (JString "test input")
ghci> parse parseJNumber "test" "345"
Right (JNumber 345.0)
ghci> parse parseJBool "test" "true"
Right (JBool True)
ghci> parse parseJNull "test" "null"
Right JNull
ghci> parse parseJValue "test" "\"jvalue test\""
Right (JString "jvalue test")
ghci> parse parseJValue "test" "789"
Right (JNumber 789.0)
parseJValue
但是,当我尝试解析true
、false
或时失败了,null
我得到了一个有趣的错误。
ghci> parse parseJValue "test" "true"
Right (JNumber *** Exception: Prelude.read: no parse
我得到了成功的解析,但解析返回 aJNumber
后跟一个错误,指出 Prelude.read 失败。我觉得我在构建解析器时缺少一些核心概念,但我看不出哪里出错了。另外,我的代码是否犯了任何初学者错误,即这些是否会被认为是“坏”的haskell?