問題の2つのバージョンを書いていますが、それらは同様の効率を持つべきだと思いますが、そうではありません。私はそれがハスケルの怠惰な評価行動に起因すると思う。誰かがあなたがnqueens2はかなり動作しますがサイズ8ハスケルの遅延評価動作の理解に役立つ
のボードのためにそれを評価するためにnqueens1 8 8またはnqueens2 8 8を呼び出すことによって、それらを評価することができ
、それは次の例のためにどのように動作するか
nqueens1 n 1 = [[i] | i <- [1..n]]
nqueens1 n k = [ i:q | i <- [1..n], q <- (nqueens1 n (k - 1)), isSafe i q k]
isSafe i q n = isSafeHelper i (zip q [(n-1),(n-2)..1])
where isSafeHelper i [] = True
isSafeHelper i (x:xs) = (i /= fst x) && abs(i - (fst x)) /= abs(n - (snd x)) &&
isSafeHelper i xs
nqueens2 n 1 = [[i] | i <- [1..n]]
nqueens2 n k = [ i:q | i <- [1..n], q <- boards, isSafe i q k]
where boards = nqueens2 n (k-1)
を説明していただけます効率的にnqueens1にパフォーマンスの問題があります。再帰呼び出し(nqueens n(k-1))が複数回評価されているためです。 Haskellの遅延評価の私の理解から、これは当てはまりません。
この現象を理解するのを手伝ってください。
ありがとうございます。
「遅延評価は、」遅れて、物事を評価についてです - ではない何かを評価する何回も回避について。 –
@DanielWagner実際には、遅延評価と名前による呼び出しの違いは、名前による呼び出しを使用して複数回評価される特定の式は、遅延評価を使用して一度だけ評価されるということです。しかし、それはここの問題とは関係ありません。 – sepp2k
@ sepp2kあなたは正しいです、私は、「怠惰な評価」の代わりに「名前による呼び出し」と言うか、「何度も何かを評価するのを避ける」の代わりに「メモ」と言って、より正確になっていたはずです。 –