在 Haskell 中使用异常处理将字符串解析为整数
string to Integer parsing with Exception Handling in Haskell
正在尝试创建 nat
类型 return [ (int, string) ]; handle zero as string
并输入 int
可以处理 negative integer also.
import Data.Char ( isDigit )
type Parser tok a = [tok] -> [(a, [tok])]
return :: a -> Parser tok a
return v = \ts -> [(v, ts)]
failure :: Parser tok a
failure = \_ -> []
item :: Parser tok tok
item [] = []
item (t:ts) = [(t, ts)]
sat :: (tok -> Bool) -> Parser tok tok
sat test = item >>= \t ->
if test t then return t
else failure
(<|>) :: Parser tok a -> Parser tok a -> Parser tok a
p1 <|> p2 = \ts -> case p1 ts of
[] -> p2 ts
rs1 -> rs1
many1 :: Parser tok a -> Parser tok [a]
many p = many1 p <|> return []
many1 p = p >>= \v ->
many p >>= \vs ->
return (v:vs)
digit = sat isDigit
首先我创建 nat 并使用 if ~ then ~ else make exception of 0.
nat :: Parser Char Int
nat = many1 digit >>= \s ->
if (s == "0") then failure
else return (read s)
它能够处理一个零。
nat "0"
> []
nat "0def"
> []
但输入0开头的连续数字时无法处理
nat "012def"
> [(12, "def")] -- probably my code only handle 1 Zero
-- expect return []
nat "000def"
> [(0, "def")] -- but i really don't know why this output is coming
-- expect return []
我试着把nat的问题搁置一旁,先做一个int。
首先我尝试使用nat来定义int。
int :: Parser Char Int
int = nat >>= \s ->
if (s < 0) then return (-s)
else return s
而且我意识到我无法让编译器识别 s 是负数。
所以我试着让它和 nat 一样。我想添加 char '-'?
int :: Parser Char Int
int = many1 digit >>= \s ->
if (s == "-") then return (read s) ++ "-"
else return (read s)
我有两个问题
为什么nat只处理1个零?我还以为many1是一步步递归解析字符串呢
如何在int中添加“-”?跟合成函数有关系吗?
我不擅长使用Haskell。有什么我想念的吗?
不要惊慌。没那么难。
- Why nat only handle 1 zero? I thought many1 is recursive parsing
string step-by-step.
你是对的 many1 digit
将在尽可能长的链上应用解析器数字。这意味着当您解析 012def
时,解析的部分是“012”,其余部分是“def”。但是你错过了错误所在。它在下面
\s -> if (s == "0") then failure
else return (read s)
一次,many1 digit
完成后,它会通过绑定 (>>=
) 向您的函数提供“012”,这是一个过程。但是“012”不是“0”。所以应用 else
部分:return (read "012")
。上下文 "def"
未修改。所以这导致答案 [12,"def"]。如您所见,问题不是绑定的第一部分,而是第二部分。既然你知道你只会得到数字(因为 many1 digit
只能解析数字),我建议你改变你的活页夹
let n = read s
in if n == 0 then failure
else n
更优雅的(单子)解决方案是可能的,但这个解决方案对于新的 haskeller 来说可能是非常可读和明确的。
- How can I add "-" in int? does it related with thins like synthetic function?
你不能。你想读一个不能翻译成数字的 Char
。所以你不能把它读成数字。这是一个简单的解析问题。您必须单独处理 '-'
。您可以在两个解析器之间进行选择。第一个解析 Char
'-'
后跟自然。第二个只解析自然。然后将结果翻译成 Int
。注意不要忘记 0
。它可以在第一个、第二个或两者中处理。这意味着您不能在两者中都使用 nat
...或者您将不得不制作第三个仅解析 0
的解析器。所以记住顺序很重要。
考虑到以前的工作,我很确定可以写这个。您已经有了数字和选择组合器。 char
解析器非常明显。你只需要考虑一下。
希望这会有所帮助。
正在尝试创建 nat
类型 return [ (int, string) ]; handle zero as string
并输入 int
可以处理 negative integer also.
import Data.Char ( isDigit )
type Parser tok a = [tok] -> [(a, [tok])]
return :: a -> Parser tok a
return v = \ts -> [(v, ts)]
failure :: Parser tok a
failure = \_ -> []
item :: Parser tok tok
item [] = []
item (t:ts) = [(t, ts)]
sat :: (tok -> Bool) -> Parser tok tok
sat test = item >>= \t ->
if test t then return t
else failure
(<|>) :: Parser tok a -> Parser tok a -> Parser tok a
p1 <|> p2 = \ts -> case p1 ts of
[] -> p2 ts
rs1 -> rs1
many1 :: Parser tok a -> Parser tok [a]
many p = many1 p <|> return []
many1 p = p >>= \v ->
many p >>= \vs ->
return (v:vs)
digit = sat isDigit
首先我创建 nat 并使用 if ~ then ~ else make exception of 0.
nat :: Parser Char Int
nat = many1 digit >>= \s ->
if (s == "0") then failure
else return (read s)
它能够处理一个零。
nat "0"
> []
nat "0def"
> []
但输入0开头的连续数字时无法处理
nat "012def"
> [(12, "def")] -- probably my code only handle 1 Zero
-- expect return []
nat "000def"
> [(0, "def")] -- but i really don't know why this output is coming
-- expect return []
我试着把nat的问题搁置一旁,先做一个int。
首先我尝试使用nat来定义int。
int :: Parser Char Int
int = nat >>= \s ->
if (s < 0) then return (-s)
else return s
而且我意识到我无法让编译器识别 s 是负数。
所以我试着让它和 nat 一样。我想添加 char '-'?
int :: Parser Char Int
int = many1 digit >>= \s ->
if (s == "-") then return (read s) ++ "-"
else return (read s)
我有两个问题
为什么nat只处理1个零?我还以为many1是一步步递归解析字符串呢
如何在int中添加“-”?跟合成函数有关系吗?
我不擅长使用Haskell。有什么我想念的吗?
不要惊慌。没那么难。
- Why nat only handle 1 zero? I thought many1 is recursive parsing string step-by-step.
你是对的 many1 digit
将在尽可能长的链上应用解析器数字。这意味着当您解析 012def
时,解析的部分是“012”,其余部分是“def”。但是你错过了错误所在。它在下面
\s -> if (s == "0") then failure
else return (read s)
一次,many1 digit
完成后,它会通过绑定 (>>=
) 向您的函数提供“012”,这是一个过程。但是“012”不是“0”。所以应用 else
部分:return (read "012")
。上下文 "def"
未修改。所以这导致答案 [12,"def"]。如您所见,问题不是绑定的第一部分,而是第二部分。既然你知道你只会得到数字(因为 many1 digit
只能解析数字),我建议你改变你的活页夹
let n = read s
in if n == 0 then failure
else n
更优雅的(单子)解决方案是可能的,但这个解决方案对于新的 haskeller 来说可能是非常可读和明确的。
- How can I add "-" in int? does it related with thins like synthetic function?
你不能。你想读一个不能翻译成数字的 Char
。所以你不能把它读成数字。这是一个简单的解析问题。您必须单独处理 '-'
。您可以在两个解析器之间进行选择。第一个解析 Char
'-'
后跟自然。第二个只解析自然。然后将结果翻译成 Int
。注意不要忘记 0
。它可以在第一个、第二个或两者中处理。这意味着您不能在两者中都使用 nat
...或者您将不得不制作第三个仅解析 0
的解析器。所以记住顺序很重要。
考虑到以前的工作,我很确定可以写这个。您已经有了数字和选择组合器。 char
解析器非常明显。你只需要考虑一下。
希望这会有所帮助。