我正在阅读reads
的源代码。 reads
定义为reads :: Read a => ReadS a
因此它只返回ReadS a
,而a必须是Read
的实例。
并且ReadS a
被定义为type ReadS a = String -> [(a, String)]
,因此从reads
返回的东西只是一个接受字符串并返回元组数组的函数。
然后我想知道为什么只定义reads
而没有ReadS a 。就像
reads :: Read a => (String -> [(a, String)])
答案 0 :(得分:11)
事物的解析器 是字符串的函数
到对的列表
事物和弦乐!- 各种来源
它有助于推理程序根据其意图考虑抽象,而不是实施。所以是的,在type ReadS a = String -> [(a, String)]
时,这是解析事物的实际目标和将ReadS
解析器链接在一起的次要因素。正如Rhymoid所指出的那样:
composeReads :: ReadS a -> ReadS b -> ReadS (a,b)
传达解析器组合的意图,并且作为一个快乐的副作用比内联等效物更简洁:
composeReads
:: (String -> [(a, String)])
-> (String -> [(b, String)])
-> (String -> [((a, b), String)])
分解这种重复是一件好事而且显而易见的事情,尤其是因为避免重复是有益的,而且还要尽可能多地增加每行有用语义内容的数量。如果我们想要改变这些解析器的实现方式,那么将它们封装在这个别名后面是一个小步骤,可以让我们避免对每个使用站点进行大量更改。
你会在各种解析器组合库中重复这一点,例如Parsec,Attoparsec和uu-parsinglib。 Parser
Parser
是一个Parser
,更像是一个黑盒子,这些东西越容易使用它们 - 分开> EM>