为什么haskell使用一种ReadS来表示一个函数?

时间:2013-08-11 18:43:35

标签: function haskell

我正在阅读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)])

1 个答案:

答案 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>