2012-01-03 25 views
6

Trong đoạn mã tổng quát sau:cách mặc định của thực thi mã trong Haskell

nat = [1..xmax] 
xmax = *insert arbitrary Integral value here* 

setA = [2*x | x <- nat] 
setB = [3*x | x <- nat] 

setC = [4*x | x <- nat] 
setD = [5*x | x <- nat] 

setOne = setA `f` setB 
setTwo = setC `f` setD 

setAll = setOne ++ setTwo 

setAllSorted = quicksort setAll 

(xin lưu ý rằng 'f' là viết tắt của một chức năng của loại

f :: Integral a => [a] -> [a] -> [a] 

đó không phải là đơn giản ++)

cách xử lý Haskell cố gắng in setAllSorted?

nó nhận được các giá trị cho setA và setB, tính setOne và sau đó chỉ giữ giá trị cho setOne trong bộ nhớ (trước khi tính toán mọi thứ khác)?

Hay Haskell giữ mọi thứ trong bộ nhớ cho đến khi nhận được giá trị cho setAllSorted?

Nếu trường hợp sau là trường hợp thì tôi sẽ chỉ định như thế nào (sử dụng các hàm chính, chức năng và tất cả những thứ khác của IO) mà thay vào đó nó thực hiện trước đây?

Tôi có thể cho chương trình biết thứ tự tính toán và thu gom rác thải không? Nếu vậy, tôi sẽ làm như thế nào?

+1

Haskell không xác định cách mã của bạn được thực thi, chỉ có kết quả là gì; câu hỏi này vốn đã được triển khai cụ thể. – ehird

Trả lời

9

Đầu của setAllSorted nhất thiết phải nhỏ hơn hoặc bằng với mọi phần tử ở đuôi. Do đó, để xác định phần đầu, tất cả các số setOnesetTwo phải được tính toán. Hơn nữa, vì tất cả các bộ đều là dạng ứng dụng không đổi, tôi tin rằng chúng sẽ không được thu gom rác sau khi được tính toán. Các con số tự nó có thể sẽ được chia sẻ giữa các bộ, nhưng các nút khuyết điểm dán chúng lại với nhau có thể sẽ không được (may mắn của bạn với một số sẽ phụ thuộc vào định nghĩa của f).

+2

Mặc dù chúng là CAF, chúng có thể được thu thập nếu trình biên dịch có thể xác định rằng chúng không được tham chiếu nữa sau khi in. Nếu chương trình là 'main = print setAllSorted', có một cơ hội tốt là GHC (với tối ưu hóa) sẽ thu thập rác các phần không cần thiết nữa. Tuy nhiên, đó chỉ là một yếu tố không đổi của bộ nhớ đỉnh. –

+0

có "yếu tố không đổi" có nghĩa là nó sẽ giảm lượng lớn dữ liệu hơn? Nghĩa là, việc giảm bộ nhớ đỉnh có tỷ lệ thuận với lượng dữ liệu được tính toán và do đó rác được thu thập? –

7

Do lười biếng, Haskell đánh giá mọi thứ theo yêu cầu. Bạn có thể nghĩ rằng việc in ấn được thực hiện ở phần cuối là "kéo" các yếu tố trong danh sách setAllSorted, và điều đó có thể kéo những thứ khác với nó.

Đó là, chạy mã này nó đi một cái gì đó như thế này:

  1. In ấn đầu tiên đánh giá các yếu tố đầu tiên của setAllSorted.
  2. Vì điều này xuất phát từ quy trình sắp xếp, nó sẽ yêu cầu tất cả các thành phần của setAll được đánh giá. (Vì phần tử nhỏ nhất có thể là phần tử cuối cùng).
  3. Đánh giá thành phần đầu tiên của setAll yêu cầu đánh giá phần tử đầu tiên là setOne.
  4. Đánh giá thành phần đầu tiên là setOne phụ thuộc vào cách f được triển khai. Nó có thể yêu cầu tất cả hoặc không có setAsetB để được đánh giá.
  5. Sau khi chúng tôi in xong phần tử đầu tiên của setAllSorted, setAll sẽ được đánh giá đầy đủ. Không có tham chiếu nào khác tới setOne, setTwo và các bộ nhỏ hơn, vì vậy, tất cả những điều này hiện đều đủ điều kiện để thu thập rác. Yếu tố đầu tiên của setAllSorted cũng có thể được khai hoang.

Vì vậy, về mặt lý thuyết, mã này sẽ giữ setAll trong bộ nhớ hầu hết thời gian, trong khi setAllSorted, setOnesetTwo sẽ có khả năng chỉ chiếm một lượng không đổi không gian bất cứ lúc nào.Tùy thuộc vào việc thực hiện f, điều tương tự cũng có thể đúng đối với các nhóm nhỏ hơn.

Các vấn đề liên quan