2012-02-16 33 views
9

Recently tôi được giới thiệu đến this OCaml code mà trong Haskell có thể được viết như sau:danh sách chức năng thuần túy "True" kép liên kết và chia sẻ của các nút

data DL a = DL [a] a [a] 

create [] = error "empty list" 
create (x:xs) = DL [] x xs 

next (DL pr x (h:tl)) = DL (x:pr) h tl 
next _ = error "end of dlist" 

prev (DL (p:pr) x tl) = DL pr p (x:tl) 
prev _ = error "start of dlist" 

mà tôi mặc dù đã không một danh sách gấp đôi liên kết thích hợp triển khai, vì nó tạo lưu trữ mới trên truyền tải. OTOH có this Haskell code:

data DList a = Leaf | Node { prev::(DList a), elt::a, next::(DList a) } 

create = go Leaf 
    where go _ []  = Leaf 
     go prev (x:xs) = current 
      where current = Node prev x next 
        next = go current xs 

Chúng ta có thể nói rằng nó là chỉ này đang đó là đúng dl-list?

Chúng tôi có thể dựa vào mã này để giới thiệu chia sẻ thực sự các nút của danh sách dl không, do đó không có bộ nhớ mới nào được tạo trên truyền tải?

Sản phẩm biến có cùng tên trong Haskell luôn đề cập đến cùng "điều" hoặc có thể tách các lần xuất hiện của biến cùng tên tham khảo bản sao riêng của điều tương tự? (chỉnh sửa để thêm nhấn mạnh).

+5

Triển khai đầu tiên là cái được gọi là _Zipper_; cho là nó có thể được cho một trong hai danh sách đơn lẻ hoặc liên kết kép. Tuy nhiên, nó không phải là một danh sách thực hiện theo đúng nghĩa của nó. – ivanm

+5

Nếu bạn đọc kỹ báo cáo Haskell, bạn không thể tìm thấy một đoạn văn nào về cách dữ liệu được biểu diễn. Xin lưu ý rằng mọi loại chia sẻ đều phụ thuộc vào việc triển khai, mặc dù chủ yếu chỉ có một vài cách hợp lý để triển khai một tính năng nhất định. – fuz

+0

Cảm ơn bạn về câu hỏi này! Tôi đã không hài lòng với tôi, theo dõi điều này. – demi

Trả lời

3

Tôi khuyên rằng sau này là triển khai "đúng", có.

Tôi không có sự thật để sao lưu nó, nhưng có vẻ như với tôi, với sự hiểu biết của tôi về việc thực hiện GHC, rằng sau này nên làm việc như thế nào bạn mong đợi một danh sách liên kết đôi để làm việc.

+0

cảm ơn! Tôi muốn chắc chắn, đặc biệt là về câu hỏi cuối cùng của tôi. :) –

+1

@WillNess Tôi tin rằng đó là vấn đề triển khai, nhưng GHC sử dụng biểu diễn dựa trên con trỏ dưới mui xe để biểu diễn cùng một điều (ví dụ: trong 'xs ++ ys', giá trị' ys' ban đầu được sử dụng như kết thúc danh sách kết hợp mới). – ivanm

6

Bạn có thể hình dung cách bố trí bộ nhớ của cấu trúc dữ liệu của bạn trông như thế nào bằng cách sử dụng gói có tên là vacuum-cairo. Cài đặt từ hackage với cabal install vacuum-cairo sau đó bạn sẽ có thể để xác minh sự khác biệt trong hai cấu trúc bởi một cái gì đó như thế này trong GHCi:

> import System.Vacuum.Cairo 
> view $ create [1..5] 

Ở đó bạn có thể thấy các nút được chia sẻ bằng cách sử dụng DList nơi như DL là hai danh sách với một yếu tố ở giữa (Như đã chỉ ra, đây là loại Dây kéo).

Lưu ý: Đây là GHC cụ thể, việc triển khai khác có thể đại diện cho dữ liệu trong bộ nhớ khác nhau, nhưng điều này sẽ là điển hình.

+0

cảm ơn, tôi hiểu nó * được cho là như thế nào. Nhưng nó đã được đề xuất (trong bài viết mà từ đầu tiên trong câu hỏi của tôi liên kết) chia sẻ không được bảo đảm. Sau đó, làm thế nào cấu trúc được cho là, và làm thế nào 'cairo' sẽ hiển thị nó cho tôi, sẽ không nhất thiết phải như thế nào trong thực tế. Tôi muốn biết, có một sự bảo đảm ít nhất là cùng một tên var là luôn luôn trỏ đến cùng một điều trong bộ nhớ, trong bất cứ điều gì thực hiện? –

+0

Có, nếu không một ví dụ như thế này sẽ không hoạt động: '(x, xs) = let y = sao chép 10 x in (chiều dài y, y)' – Oliver

+0

Tôi nghĩ rằng nó vẫn hoạt động, vì không có chu trình trong luồng phụ thuộc trong ví dụ của bạn. –

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