如何创建一个解析器来分隔 Haskell 中的数字(不是数字)

How to create a parser that separates numbers (not digits) in Haskell

我正在尝试实现一种平衡化学反应的算法,给定以下形式的输入反应(通过两行 I/O):

XNXNXN XNXNXN ... XNXNXN

YNYNYN YNYNYN ... YNYNYN

其中第一行是反应物列表,第二行是产物列表。 X代表一个原子,N代表一个正整数。

我正在尝试创建一个列表,其输出如下所示:

 N, N, N,   ... N N
-N, -N, -N, ... -N -N.

但是,我不知道如何为整数而不是数字执行此操作。我可以尝试使用解析器 分割点 和

isElem x [1..], 

但问题是(通过这个实现)我需要以相反的顺序评估列表,如果列表是无限的,这是不可能的,如果列表很长,计算量很大,因为较小的数字在化学方程式中更常见。

否则,我会在数字的开头和结尾之间添加空格。

我认为解决方案是让它在看到字符时将布尔值更新为 false。每当它这样做时,它都会向后移动,直到遇到另一个非数字,连接成一个字符串,然后反转列表,因为它正在向后移动。然后它对剩余的列表应用相同的函数,终止于一个空列表。

问题是我才刚刚开始Haskell,不知道如何实现这个算法

你是这个意思吗? (我希望你能找出其他变体的缺点)

import Data.Char

go :: [Int] -> Int -> String -> [Int]
go res n [] = reverse $ n:res
go res n (h:t)
  | h `elem` "1234567890"  = go res (n * 10 + ord h - ord '0') t
  | n == 0 = go res 0 t
  | otherwise  = go (n:res) 0 t

parse = go [] 0

第一个参数是在计算过程中累积的总结果。第二个是目前内置的整数。第三个是输入字符串。

每当我们看到不是数字的东西时,我们通过将其添加到累加器并继续将新的内置整数设置为 0 来完成构建数字。当列表为空时(意味着我们到达了输入的末尾),我们 return 反转累加器。这是因为我们将它建立在颠倒顺序的堆栈上。它不会对性能产生严重影响,因为整个操作无论如何都是线性的。

主程序只是以空累加器和 0 作为当前解析的整数来启动逻辑。