このコードを理解するには、次の 2 つのスキルが必要です。
naturals = (1 : map '\n->n+1' naturals
無限の可能性がある「定義」(自然数のセット: )、または処理されたリクエストのリスト) と、実際のデータをこれらの定義にマッピングするプロセスである「縮小」を区別する
- このクライアント/サーバー アプリケーションの構造を確認してください: これは、互いに通信しているプロセスのペアにすぎません: 「client-server」は悪い名前です。実際には、「wallace-gromit」または「foo-bar」と呼ばれるべきでした。哲学者などの話ですが、対称的です。2 つの当事者はピアです。
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 に伝えます。これについては、 Haskellのウィキブックにすばらしいトピックがあります (「Lazy Pattern Matching」を探してください)。