Haskell hỗ trợ một số thao tác cơ bản để đệ quy thông qua danh sách, như head
, tail
, init
và last
. Tôi tự hỏi, nội bộ, Haskell đại diện cho dữ liệu danh sách của nó như thế nào? Nếu đó là danh sách được liên kết đơn lẻ, thì các hoạt động init
và last
có thể trở nên tốn kém khi danh sách tăng lên. Nếu đó là danh sách được liên kết kép, tất cả bốn hoạt động có thể được thực hiện O(1)
khá dễ dàng, mặc dù chi phí của một số bộ nhớ. Dù bằng cách nào, điều quan trọng là tôi phải biết, vì vậy tôi có thể viết mã thích hợp. (mặc dù, các đặc tính của lập trình chức năng có vẻ là một trong những "hỏi những gì nó làm, không phải như thế nào nó").Trình bày nội bộ danh sách Haskell?
Trả lời
Danh sách được trình bày dưới dạng ... danh sách được liên kết đơn lẻ. Định nghĩa được cho bởi:
data [] a = [] | a : [a]
mà bạn có thể viết như sau:
data List a = Empty | Cons a (List a)
Cách bố trí bộ nhớ được hoàn toàn xác định bởi đây.
- Constructors là đống phân bổ
- lĩnh vực đa hình nội bộ là con trỏ đến nút phân bổ khác
- Cột sống là lười biếng
Vì vậy, bạn kết thúc với một cái gì đó như thế này:
Vì vậy, head
là O (1) trên cấu trúc này, trong khi last
hoặc (++)
là O (n)
Không có phép thuật để cấu trúc dữ liệu trong Haskell - nét thẳng về phía trước của họ làm hoàn toàn rõ ràng những gì mức độ phức tạp sẽ được (modulo lười biếng). Nếu bạn cần sự phức tạp khác nhau, hãy sử dụng một cấu trúc khác (chẳng hạn như IntMap, Trình tự, HashMap, Vector v.v.) ...
Cảm ơn câu trả lời.Tôi không chắc nó cần thiết để nhấn mạnh rõ ràng/rõ ràng câu trả lời này nên được - Tôi là một người mới bắt đầu Haskell, và đến từ C đó là một sự thay đổi rất lớn, vì vậy tôi vẫn tìm ra công cụ. Dù sao một lần nữa cảm ơn. –
Ồ, tôi không có nghĩa là "dễ dàng" của nó, chỉ là không có ma thuật liên quan. Nếu bạn chỉ cần nhìn vào định nghĩa kiểu dữ liệu, thì tất cả đều có thể phát sinh được. –
Hai cảnh báo lớn: ** lười biếng ** và ** tổng hợp **. Sự lười biếng có nghĩa là, ví dụ, trong 'xs ++ ys' bạn chỉ phải trả chi phí của phần phụ thêm vào phạm vi mà bạn duyệt qua danh sách kết quả; 'head (xs ++ ys)' là O (1), không phải O (n). Fusion có nghĩa là nhiều hoạt động không phải trả thêm chi phí nào cho quá trình truyền tải; ví dụ, 'map (* 2) (xs ++ ys)' chi phí ít hơn tổng chi phí của 'map (* 2)' và '++', bởi vì GHC loại bỏ danh sách trung gian được tạo ra. –
danh sách Haskell đang đơn lẻ liên kết, vì vậy cons
, head
và tail
là O (1) trong khi init
và last
là O (n ).
Nếu bạn cần hiệu suất tốt hơn, hãy cân nhắc sử dụng loại Seq
từ Data.Sequence, cung cấp truy cập O (1) cho cả hai đầu của danh sách. Bên trong nó sử dụng 2-3 finger trees.
- 1. Danh sách mã trong khung trình bày beamer LaTeX
- 2. Trình bày một lớp như một dict hoặc danh sách
- 3. Danh sách Haskell khác biệt
- 4. Nội dung trang trình bày/chuyển trang
- 5. Haskell: Danh sách vs Luồng
- 6. Haskell tính danh sách loại
- 7. Haskell - lồng danh sách rỗng
- 8. Làm việc trên danh sách các danh sách trong Haskell
- 9. Haskell đa hình và danh sách
- 10. Cách chèn phần tử vào danh sách nội bộ MongoDB?
- 11. Danh sách nội dung của bộ nhớ cache véc ni?
- 12. Đệ quy sử dụng danh sách - Haskell
- 13. Kiểm tra nội bộ của các chức năng trong Haskell
- 14. Chia nhỏ danh sách trong haskell
- 15. danh sách Giáo Hội trong Haskell
- 16. Học Haskell: danh sách hiểu trong C#
- 17. Haskell Danh sách tuple Tìm kiếm
- 18. Haskell: Chuyển đổi danh sách dữ liệu
- 19. Ổ đĩa danh sách Haskell trong Windows
- 20. Haskell - Danh sách Hiểu vị từ Optimization
- 21. Haskell: lọc danh sách heterogenous theo loại
- 22. Ghép nối các danh sách trong Haskell
- 23. Nhận danh sách phụ trong Haskell
- 24. sáp nhập hai danh sách trong Haskell
- 25. Trình bày một tập hợp các URL trong một danh sách dưới dạng cấu trúc cây
- 26. Xóa phần tử danh sách giống như thông báo trên trang trình bày trong Android
- 27. Flexslider Thêm Trang trình bày (Nội dung Ajax)
- 28. Các danh tiếng của một danh sách - Haskell
- 29. Haskell - chuyển đổi từ Danh sách sang Data.Vector
- 30. Haskell: kiểm tra xem danh sách có chứa "danh sách con" cụ thể
"hỏi nó làm gì, không phải như thế nào" Không phải nếu bạn lo ngại về việc viết mã là hợp lý nhanh chóng;) –
Vâng, đó là những gì tôi nghĩ :-) Do đó câu hỏi của tôi. –
"Nếu đó là danh sách được liên kết gấp đôi, tất cả bốn hoạt động có thể được thực hiện O (1) khá dễ dàng", thật không dễ dàng nếu bạn muốn giữ nguyên chức năng, vì vậy các danh sách được liên kết gấp đôi bình thường không được sử dụng nhiều trong Haskell . Làm mọi thứ trong _O_ (1) trong khi hoàn toàn là chức năng đòi hỏi cấu trúc dữ liệu phức tạp hơn - tuy nhiên hóa ra, bằng cách khai thác sự lười biếng của Haskell, bạn có thể làm được nhiều hơn với các hoạt động _O_ (1) (hoặc theo cách nào đó được phân bổ _O_ (_n_), gần như là tốt) trên các danh sách liên kết đơn lẻ được liên kết của nó hơn là có thể bằng bất kỳ ngôn ngữ thủ tục nào. – leftaroundabout