Function 为什么haskell使用一种读取类型来表示函数?

Function 为什么haskell使用一种读取类型来表示函数?,function,haskell,Function,Haskell,我正在阅读reads的源代码读取定义为读取::读取a=>读取a 因此,它只返回读取a,而a必须是读取的实例 而ReadS a被定义为type ReadS a=String->[(a,String)],因此从ReadS返回的东西只不过是一个接受字符串并返回元组数组的函数 那么我想知道为什么只定义读取而不定义读取。就像 reads::reada=>(String->[(a,String)]) 事物的解析器 是字符串中的函数 到配对列表 所有的东西和绳子 -各种来源 它有助于对程序进行推理,从而根据抽

我正在阅读
reads
的源代码<代码>读取定义为
读取::读取a=>读取a
因此,它只返回
读取a
,而a必须是
读取
的实例

ReadS a
被定义为
type ReadS a=String->[(a,String)]
,因此从
ReadS
返回的东西只不过是一个接受字符串并返回元组数组的函数

那么我想知道为什么只定义
读取
而不定义读取
。就像
reads::reada=>(String->[(a,String)])

事物的解析器
是字符串中的函数
到配对列表
所有的东西和绳子

-各种来源

它有助于对程序进行推理,从而根据抽象的意图而不是实现来思考抽象。是的,虽然
类型读取a=String->[(a,String)]
,但这是解析事物和将
读取的
解析器链接在一起的实际目标的次要目标。正如所指出的那样:

composeReads :: ReadS a -> ReadS b -> ReadS (a,b)
传达了解析器组合的意图,并且作为一个愉快的副作用,它比内联的等价物更加简洁:

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


您可以在各种解析器组合器库中看到这一点,如Parsec、attopassec和uu parsinglib。
解析器
是一个
解析器
是一个
解析器
,这些东西越像一个黑匣子,它们的使用和实现就越容易分开进行。

基本上是可读性。给一个概念起一个名字可以让你更容易思考和谈论。例如:
composeAds::ReadS a->ReadS b->ReadS(a,b)
composeAds::(String->[(a,String)])->(String->[(b,String)]->(String->[(a,b,String)])
可读性更强。谢谢你的详细解释。我会记得“解析器就是解析器就是解析器,这些东西越像一个黑匣子,”:)