绳子到整数解析,并在Haskell中进行例外处理

发布于 2025-02-04 10:00:32 字数 2090 浏览 2 评论 0原文

尝试制作类型nat哪个返回[(int,string)];将零作为字符串

和类型 int 处理,它也可以处理负整数。

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并使用〜然后使用〜然后〜else〜其他例外。

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) 

我有两个问题

  1. 为什么nat只处理1个零?我以为Muran1是递归解析字符串。

  2. 如何在int中添加“ - ”?它与诸如合成功能之类的细胞有关吗?

我在使用Haskell方面很虚弱。我缺少什么吗?

Trying to make type nat which return [ (int, string) ]; handle zero as string

and type int which can handle 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 

first I make nat and use if ~ then ~ else make exception of 0.

nat :: Parser Char Int 
nat = many1 digit >>= \s -> 
      if (s == "0") then failure 
                    else return (read s) 

It was able to handle one zero.

nat "0"
> [] 

nat "0def" 
> [] 

but can't handle when consecutive numbers starting with 0 come to input.

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 [] 

I tried to put aside the problem about nat and make an int first.

first I tried to use nat to define int.

int :: Parser Char Int 
int = nat >>= \s -> 
      if (s < 0) then return (-s) 
                 else return s 

And I realize that i can't make to compiler recognize that s is negative.

so i tried to make it simillar as nat. which I want to add char '-'?

int :: Parser Char Int 
int = many1 digit >>= \s -> 
      if (s == "-") then return (read s) ++ "-"  
                    else return (read s) 

I have two question

  1. Why nat only handle 1 zero? I thought many1 is recursive parsing string step-by-step.

  2. How can I add "-" in int? does it related with thins like synthetic function?

I am weak at using Haskell. is there something i'm missing?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

べ映画 2025-02-11 10:00:32

不要恐慌。这不是那么困难。

  1. 为什么Nat只处理1个零?我认为许多人是递归解析
    字符串逐步。

您是正确的MOUS1 DIGIT将在可能的较长链上应用解析器数字。这意味着,当您解析012DEF解析部分为“ 012”,其余部分为“ DEF”。但是您缺少错误的位置。在以下内容中

\s -> if (s == "0") then failure 
                    else return (read s)

mus1 digit完成它通过bind(&gt;&gt; =)向您的函数提供了“ 012”,并且是过程。但是“ 012”不是“ 0”。因此,应用了else零件:return(读取“ 012”)。上下文“ def”未修改。因此,这将导致答案[12,“ def”]。如您所见,问题不是绑定的第一部分,而是第二部分。既然您知道您只会获得数字(因为Moan1 Digit只能分析数字),我建议您使用

let n = read s 
in if n == 0 then failure 
             else n

更优雅的(monadic)解决方案更改活页夹,但这可能是可以读取的。并明确针对新的Haskeller。

  1. 如何在int中添加“ - ”?它是否与诸如合成功能之类的细胞有关?

你不能。您想读取无法将其翻译成数字的char。因此,您无法将其视为数字。这是一个简单的解析问题。您必须单独处理' - ' - ' - '。您可以在两个解析器之间使用选择。第一个解析char ' - ',其次是自然。第二次解析自然。然后将结果转换为int。注意不要忘记0。它可以在第一,第二或两者中进行处理。这意味着您不能在两者中使用nat ...或者您必须制作第三个解析器,仅解析0。因此请记住,该顺序很重要。

我很确定,考虑到以前的工作,可以写这篇文章。您已经拥有数字和选择组合。 char解析器很明显。您只需要考虑一下即可。

希望这会有所帮助。

Don't panic. It is not so difficult.

  1. Why nat only handle 1 zero? I thought many1 is recursive parsing
    string step-by-step.

You are right many1 digit will apply the parser digit on the longer chain possible. This means that when you are parsing 012def the parsed part is "012" and the remaining is "def". But you are missing where the error is. It is in the following

\s -> if (s == "0") then failure 
                    else return (read s)

Once, many1 digit finish it provides "012" to your function via the bind (>>=) and it is process. But "012" is not "0". So the else part is applied : return (read "012"). The context "def" is not modified. So this results to the answer [12,"def"]. As you can see the problem is not the first part of the bind, but the second one. Since you know that you will only get digit (because many1 digit can only parse digit), I suggest that you change your binder with

let n = read s 
in if n == 0 then failure 
             else n

More elegant (monadic) solution are possibles, but this one is probably quite readable and explicit for new haskeller.

  1. How can I add "-" in int? does it related with thins like synthetic function?

You can't. You want to read a Char that cannot be translate as a digit. So you can't read it as digit. This is a simple parsing problem. You have to deal with the '-' separately. You can use a choice between two parsers. The first parses the Char '-' followed by a natural. The second parses only natural. Then translate the result in an Int. Take care to not forget the 0. It can be handle in the first, the second or both. This means that you can't use nat in both... or you will have to make a third parser that only parse 0. So remember that the order is important.

I am pretty sure that can be write this considering the previous work. You already have the digit and the choice combinator. The char parser is pretty obvious. You just have to think about it.

Hope this will help.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文