Parsing 为带十进制的正JSON数编写解析器
根据Yorgey教授的以下定义:Parsing 为带十进制的正JSON数编写解析器,parsing,haskell,Parsing,Haskell,根据Yorgey教授的以下定义: newtype Parser a=Parser{runParser::String->Maybe(a,String)} 以及以下代数数据类型: type Key = String data Json = JObj Key JValue | Arr [JValue] deriving Show data JValue = N Double | S String
newtype Parser a=Parser{runParser::String->Maybe(a,String)}
以及以下代数数据类型:
type Key = String
data Json = JObj Key JValue
| Arr [JValue]
deriving Show
data JValue = N Double
| S String
| B Bool
| J Json
deriving Show
我编写了以下函数来解析带小数点的位置JSON编号:
parseDecimalPoint :: Parser Char
parseDecimalPoint = satisfy (== '.')
type Whole = Integer
type Decimal = Integer
readWholeAndDecimal :: Whole -> Decimal -> Double
readWholeAndDecimal w d = read $ (show w) ++ "." ++ (show d)
parsePositiveDecimal:: Parser JValue
parsePositiveDecimal = (\x _ y -> f x y) <$> (
(oneOrMore (satisfy isNumber)) <*> parseDecimalPoint <*>
(zeroOrMore (satisfy isNumber)) )
where
f x [] = N (read x)
f x y = N (-(readWholeAndDecimal (read x) (read y)))
parseDecimalPoint::Parser Char
parseDecimalPoint=满足(='。)
类型整型=整数
类型Decimal=整数
readwholeandecimal::整->十进制->双精度
readwholeandecimal w d=read$(show w)++”+(show d)
parsePositiveDecimal::Parser JValue
parsePositiveDecimal=(\x y->f x y)(
(一个或多个(满足isNumber))解析小数点
(零或更多(满足isNumber)))
哪里
f x[]=N(读取x)
f x y=N(-readwholeandecimal(read x)(read y)))
但是,我得到了以下编译时错误:
JsonParser.hs:30:25:
Couldn't match expected type ‘t0 -> [Char] -> JValue’
with actual type ‘JValue’
The lambda expression ‘\ x _ y -> f x y’ has three arguments,
but its type ‘String -> JValue’ has only one
In the first argument of ‘(<$>)’, namely ‘(\ x _ y -> f x y)’
In the expression:
(\ x _ y -> f x y)
<$>
((oneOrMore (satisfy isNumber)) <*> parseDecimalPoint
<*> (zeroOrMore (satisfy isNumber)))
JsonParser.hs:30:49:
Couldn't match type ‘[Char]’ with ‘Char -> [Char] -> String’
Expected type: Parser (Char -> [Char] -> String)
Actual type: Parser [Char]
In the first argument of ‘(<*>)’, namely
‘(oneOrMore (satisfy isNumber))’
In the first argument of ‘(<*>)’, namely
‘(oneOrMore (satisfy isNumber)) <*> parseDecimalPoint’
JsonParser.hs:30:25:
无法匹配预期的类型“t0->[Char]->JValue”
实际类型为“JValue”
lambda表达式“\x\uy->f x y”有三个参数,
但是它的类型'String->JValue'只有一个
在“()”的第一个参数中,即“(\x_'y->fxy)”
在表达式中:
(\x\uy->f x y)
((一个或多个(满足isNumber))解析小数点
(零或更多(满足isNumber)))
JsonParser.hs:30:49:
无法将类型“[Char]”与“Char->[Char]->String”匹配
预期类型:解析器(Char->[Char]->String)
实际类型:解析器[Char]
在“()”的第一个参数中,即
“(一个或多个(满足isNumber))”
在“()”的第一个参数中,即
“(一个或多个(满足isNumber))parseDecimalPoint”
在我的parsePositiveDecimal
函数中,我对类型的理解是:
(String->Char->String->JValue)(解析器字符串解析器字符串)
我已经学习了一些使用
和
制作解析器的示例。但我并不是完全在摸索这些类型
如果您能帮助我们理解它们,我们将不胜感激。仙人掌是正确的。我将在类型上展开一点
::函子f=>(a->b)->fa->fb
我们的f
这里是解析器
,
的第一个参数的类型是String->Char->String->JValue
。请记住,这可以理解为一个函数,它接受一个String
,并返回一个函数Char->String->JValue
,因此a
类型变量用String
填充
从中,我们可以看到
的第二个参数需要是解析器字符串类型one或more(满足isNumber)
具有该类型
综上所述,我们现在有:
(\x\uy->fxy)(一个或多个(满足isNumber)):解析器(Char->String->JValue)
我们已经从一个包含3个参数的函数(根本不涉及解析器)转变为一个包含2个参数的函数(包装在解析器中)。
若要将此函数应用于它的下一个参数Char
,我们需要:
()::应用程序f=>f(a->b)->f a->f b
f
又是Parser
,而a
这里是Char
parseDecimalPoint::Parser Char
的右侧具有所需的类型
(\x\uy->fxy)(一个或多个(满足isNumber))parseDecimalPoint::Parser(String->JValue)
我们再做一次,以获得:
(\x\uy->fxy)一个或多个(满足isNumber)parseDecimalPoint零个或多个(满足isNumber)::Parser JValue
我利用了知道运算符的优先级和关联性的优势,删除了一些括号。这就是我看到大多数这样的代码编写的方式,但也许Cactus的版本更清楚。甚至全括号版本,强调关联性:
((\x\uy->f x y)
(一个或多个(满足isNumber)))
(小数点)
(zeroOrMore(满足isNumber)):解析器JValue
它应该用括号括起来作为(\x\uy->f x y)(一个或多个(满足isNumber))parseDecimalPoint(zeroOrMore(满足isNumber)
。
JsonParser.hs:30:25:
Couldn't match expected type ‘t0 -> [Char] -> JValue’
with actual type ‘JValue’
The lambda expression ‘\ x _ y -> f x y’ has three arguments,
but its type ‘String -> JValue’ has only one
In the first argument of ‘(<$>)’, namely ‘(\ x _ y -> f x y)’
In the expression:
(\ x _ y -> f x y)
<$>
((oneOrMore (satisfy isNumber)) <*> parseDecimalPoint
<*> (zeroOrMore (satisfy isNumber)))
JsonParser.hs:30:49:
Couldn't match type ‘[Char]’ with ‘Char -> [Char] -> String’
Expected type: Parser (Char -> [Char] -> String)
Actual type: Parser [Char]
In the first argument of ‘(<*>)’, namely
‘(oneOrMore (satisfy isNumber))’
In the first argument of ‘(<*>)’, namely
‘(oneOrMore (satisfy isNumber)) <*> parseDecimalPoint’