理解该代码需要两个技能:
- distinguishing between definition , which may be infinite (like the set of natural numbers:
naturals = (1 : map
->n+1 naturals
), or the list of processed requests) and reduction , which is the process of mapping actual data to these definitions
- seeing the structure of this client-server application: it s just a pair of processes talking to eachother: client-server is a bad name, really: it should have been called wallace-gromit or foo-bar , or talking philosophers or whatever, but it s symmetrical: the two parties are peers.
As Jon already stated, reduction works in a lazy way (aka call by need ): take 2 naturals
would not first evaluate the complete set of naturals, but just take the first one, and prepend that to take 1 (map
->n+1 naturals)
, which would reduce to [1,(1+1) ] = [1,2].
现在客户端服务器应用程序的结构是这样的(在我看来):
server
is a way to create a list of responses out of a list of requests by using the process
function
client
is a way to create a request based on a response, and append the response of that request to the list of responses.
如果你仔细看,你会发现两者都是从y:ys中创建x:xs的方法。因此,我们可以平等地称它们为华莱士
和格罗米特
。
如果仅使用响应列表调用client
,那么理解起来将会很容易。
someresponses = wallace 0 [1,8,9] -- would reduce to 0,1,8,9
tworesponses = take 2 someresponses -- [0,1]
如果响应不是字面上已知的,而是由产生的,我们可以说
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列表参数的内容不需要被约简——如果它看到一个列表,那就足够了。在Haskell的一个wikibook上有一个很好的话题(查找“惰性模式匹配”)。