Vấn đề của bạn không phải là trực tiếp takeWhile
, mà là danh sách hiểu.
[x | x <- primes, n `mod` x == 0]
Đối n = 24
, chúng tôi nhận 24 `mod` 2 == 0
và 24 `mod` 3 == 0
, vì vậy giá trị của danh sách hiểu này bắt đầu với 2 : 3 : ...
. Nhưng hãy xem xét phần ...
.
Việc hiểu danh sách phải tiếp tục kéo các giá trị từ primes
và kiểm tra 24 `mod` x == 0
. Vì không còn yếu tố chính nào của 24
, sẽ không có gì vượt qua bài kiểm tra đó và được phát ra như là giá trị thứ ba của việc hiểu danh sách. Nhưng vì luôn có một nguyên tố khác để kiểm tra, nó sẽ không bao giờ dừng lại và kết luận rằng đuôi còn lại của danh sách trống.
Bởi vì điều này được đánh giá rất lười biếng, nếu bạn chỉ yêu cầu hai yếu tố đầu tiên của danh sách này thì bạn ổn. Nhưng nếu chương trình của bạn có nhu cầu thứ ba (hoặc thậm chí chỉ biết có hay không có là yếu tố thứ ba), thì việc hiểu danh sách sẽ chỉ xoay vòng mãi mãi để tìm ra.
takeWhile (< 24)
tiếp tục kéo các phần tử khỏi đối số của nó cho đến khi tìm thấy phần tử không phải là < 24
. 2
và 3
cả hai đều vượt qua bài kiểm tra đó, vì vậy takeWhile (< 24)
không cần phải biết yếu tố thứ ba của việc hiểu danh sách là gì.
Nhưng nó không thực sự là vấn đề với takeWhile
; vấn đề là bạn đã viết một danh sách hiểu để tìm tất cả các yếu tố chính (và không có gì khác), và sau đó cố gắng sử dụng một bộ lọc trên các kết quả để cắt đứt sự khám phá vô tận của tất cả các số nguyên tố cao hơn không thể là yếu tố.Điều đó không thực sự có ý nghĩa nếu bạn dừng lại để suy nghĩ về nó; theo định nghĩa, bất kỳ thứ gì không phải là yếu tố chính không thể là thành phần của danh sách đó, do đó bạn không thể lọc ra các yếu tố không lớn hơn n
từ danh sách đó. Thay vào đó, bạn cần lọc đầu vào để hiểu danh sách đó để nó không cố gắng khám phá một không gian vô hạn, như câu trả lời của @ n.m.
Lưu ý rằng danh sách '' [x | x <- số nguyên tố, 10 'mod' x == 0]' 'là _not_' [2,5] ', nhưng giống như '2: 5: infiniteLoop', bởi vì sau' 5' vô hạn nhiều số nguyên tố 'x' sẽ là đã cố gắng vì họ có thể vượt qua bài kiểm tra. Tất nhiên chúng tôi biết họ sẽ không, nhưng danh sách hiểu không biết điều đó. Sau đó 'takeWhile' bị kẹt trong vòng lặp. – chi
@chi Vâng, tôi biết rằng nó sẽ là một danh sách vô hạn, cảm ơn bạn. Nhưng tôi nghĩ rằng 'takeWhile' sẽ ngừng đánh giá danh sách vô hạn khi vị từ không giữ nữa. –
Không. Nó không phải là một danh sách vô hạn. Trên đó 'takeWhile' sẽ không có vấn đề gì. Hãy thử 'takeWhile (<= 10) [1 ..]' và 'takeWhile (<= 10) (1: 2: 5: cho f n = f (n + 1) trong f 3)'. Ở đây '[1 ..]' là một danh sách vô hạn, trong khi '1: 2: 5: ...' không phải là - nó là một danh sách với một cột sống không xác định sau phần tử thứ 3 của nó. Trong một danh sách vô hạn, 'n danh sách' sẽ luôn luôn quay trở lại, thay vào đó khi cột sống không xác định, nó sẽ không. – chi