5

我正在阅读的源代码readsreads被定义为reads :: Read a => ReadS a 所以它只是返回ReadS a,而 a 必须是Read.

AndReadS a被定义为type ReadS a = String -> [(a, String)],所以返回的东西reads只是一个函数,它接受一个字符串并返回一个元组数组。

然后我想知道为什么只定义reads没有 ReadS a。就像 reads :: Read a => (String -> [(a, String)])

4

1 回答 1

11

事物解析器
是从字符串
到事物和字符串对列表的函数

— 各种来源

它有助于推理程序以根据其意图而不是实现来考虑抽象。所以是的,虽然type ReadS a = String -> [(a, String)],这是解析事物和将ReadS解析器链接在一起的实际目标的次要目标。正如Rhyoid指出的那样:

composeReads :: ReadS a -> ReadS b -> ReadS (a,b)

传达了解析器组合的意图,并且作为一个快乐的副作用,它比内联的等价物更简洁:

composeReads
  :: (String -> [(a, String)])
  -> (String -> [(b, String)])
  -> (String -> [((a, b), String)])

排除这种重复是一件好事且显而易见的事情,不仅因为避免重复很好,而且还可以尽可能多地增加每行有用语义内容的数量。如果我们想改变这些解析器的实现方式,那么将它们封装在这个别名后面是一小步,可以让我们避免对每个使用站点进行大规模更改。

您会在 Parsec、Attoparsec 和 uu-parsinglib 等各种解析器组合库中看到这种情况。A Parseris a Parseris a Parser,这些东西越像黑盒子,就越容易分别使用和实现它们。<em>。

于 2013-08-12T05:24:13.140 回答