Gentle Introductionを読んでいて、2つのジェネレーターを含むリスト内包表記で、右端のジェネレーターが「最速」で繰り返されるのはなぜか疑問に思っています(つまり、最も内側のループにコンパイルされると思います)。次のGHCi出力を確認します。
*Main> concat [[(x,y) | x <- [0..2]] | y <- [0..2]]
[(0,0),(1,0),(2,0),(0,1),(1,1),(2,1),(0,2),(1,2),(2,2)]
*Main> [(x,y) | x <- [0..2], y <- [0..2]]
[(0,0),(0,1),(0,2),(1,0),(1,1),(1,2),(2,0),(2,1),(2,2)]
左端のジェネレーターが最も速く繰り返された場合、上記の2つの式は同じ値になります。これにより、この規則を選択するのが自然になります。
では、なぜ反対の規則が選ばれたのか誰かが知っていますか?PythonにはHaskellと同じ規則があることに気付きました(おそらくHaskellから借りたのでしょうか?)。Pythonの世界では、「forループを作成する順序であるため」という順序が選択されたようですが、私は、forループの観点から考えることは、ほとんどのHaskellプログラマーが行うこととまったく同じではないことを収集します...
考え?
以下のルイ・ワッサーマンの答えに対する私のコメントから:
ここでは、命令型の理解の説明に対応する順序は、リストのネストに対応するよりも自然であると考えられていたと思います。つまり、本質的に、これに関するHaskellの説明は、質問でリンクしたPythonの説明と同じです。結局のところ、そう思われます。