理解这段代码需要两个技巧:
- 区分“定义”,它可能是无限的(如自然数集:)
naturals = (1 : map '\n->n+1' naturals
,或已处理请求的列表)和“减少”,这是将实际数据映射到这些定义的过程
- 看看这个客户端-服务器应用程序的结构:它只是一对相互交谈的进程:“客户端-服务器”是一个坏名字,真的:它应该被称为“wallace-gromit”或“foo-bar”,或者说话的哲学家或其他什么,但它是对称的:两方是同行。
正如Jon已经说过的那样,减少以一种懒惰的方式工作(又名“按需调用”):take 2 naturals
不会首先评估完整的自然集,而只是取第一个,并将其添加到take 1 (map '\n->n+1' naturals)
,这将减少为 [1,( 1+1) ] = [1,2]。
现在客户端服务器应用程序的结构是这样的(在我看来):
server
是一种使用process
函数从请求列表中创建响应列表的方法
client
是一种基于响应创建请求并将该请求的响应附加到响应列表的方法。
如果仔细观察,您会发现两者都是“从 y:ys 创建 x:xs 的一种方式”。所以我们可以均匀地称它们为wallace
和gromit
。
现在很容易理解是否client
只使用响应列表来调用:
someresponses = wallace 0 [1,8,9] -- would reduce to 0,1,8,9
tworesponses = take 2 someresponses -- [0,1]
如果响应不是字面上已知的,而是由 产生的gromit
,我们可以说
gromitsfirstgrunt = 0
otherresponses = wallace gromitsfirstgrunt (gromit otherresponses)
twootherresponses = take 2 otherresponses -- reduces to [0, take 1 (wallace (gromit ( (next 0):...) )]
-- reduces to [0, take 1 (wallace (gromit ( 0:... ) ) ) ]
-- reduces to [0, take 1 (wallace (1: gromit (...) ) ) ]
-- reduces to [0, take 1 (1 : wallace (gromit (...) ) ) ]
-- reduces to [0, 1 ]
两个对等方之一需要“开始”讨论,因此提供给wallace
.
还要注意 : 模式之前的 ~gromit
这告诉 Haskell 不需要减少 list 参数的内容 - 如果它看到它是一个列表,那就足够了。在有关 Haskell的 wikibook 中有一个很好的主题(查找“惰性模式匹配”)。