【发布时间】:2012-03-13 15:03:32
【问题描述】:
我需要扫描一个文档并为文件中的每个字符串累积不同函数的输出。在文件的任何给定行上运行的函数取决于该行中的内容。
通过对我想要收集的每个列表进行完整的文件传递,我可以非常低效地做到这一点。示例伪代码:
at :: B.ByteString -> Maybe Atom
at line
| line == ATOM record = do stuff to return Just Atom
| otherwise = Nothing
ot :: B.ByteString -> Maybe Sheet
ot line
| line == SHEET record = do other stuff to return Just Sheet
| otherwise = Nothing
然后,我会将这些函数中的每一个映射到文件中的整个行列表,以获得原子和表格的完整列表:
mapper :: [B.ByteString] -> IO ()
mapper lines = do
let atoms = mapMaybe at lines
let sheets = mapMaybe to lines
-- Do stuff with my atoms and sheets
但是,这是低效的,因为我正在为我尝试创建的每个列表映射整个字符串列表。相反,我只想在行字符串列表中映射一次,在我移动时识别每一行,然后应用适当的函数并将这些值存储在不同的列表中。
我的C心态想做这个(伪代码):
mapper' :: [B.ByteString] -> IO ()
mapper' lines = do
let atoms = []
let sheets = []
for line in lines:
| line == ATOM record = (atoms = atoms ++ at line)
| line == SHEET record = (sheets = sheets ++ ot line)
-- Now 'atoms' is a complete list of all the ATOM records
-- and 'sheets' is a complete list of all the SHEET records
Haskell 的方法是什么?我根本无法让我的函数式编程思维提出解决方案。
【问题讨论】:
-
这几乎是正确的,只需将
atoms和sheets作为累加器变量传递,最后作为元组返回。 -
我不确定我是否遵循。我上面的伪代码在 Haskell 中是无稽之谈。 Haskell 不仅没有 for 循环,而且在 do 结构中也没有保护。此外,我对返回元组并不感兴趣。上面显示的是一个例子。如果我想返回 100 种不同类型的列表怎么办?
-
这就是我说
almost的原因。如果您不知道需要生成的列表的数量和种类,则无法在一个函数中完成。就是这么简单。请记住,您的函数需要有一个类型。如果,OTOH,您知道它始终是一个 [a] 列表,并且所有提取函数都是相同的 a,您可以返回列表列表或列表映射。 -
你不能有
data ParseResult = PAtom Atom | PSheet Sheet,映射一个B.ByteString -> ParseResult,然后定义(patoms, rest) = partition isAtom parseRes和atoms = fromPAtom patoms和sheets = fromPSheet rest吗? -
@Ptival:你的回答真的很有趣。你能把它充实起来吗?我真的很喜欢使用条件数据类型的想法,但我不确定您是如何使用它们的。
标签: list haskell functional-programming