Vì có cách để trói đầu và đuôi của danh sách thông qua đối sánh mẫu, tôi tự hỏi bạn có thể sử dụng đối sánh mẫu để ràng buộc phần tử cuối cùng của danh sách không?Bạn có thể sử dụng đối sánh mẫu để ràng buộc thành phần cuối cùng của danh sách không?
Trả lời
Có, bạn có thể sử dụng tiện ích mở rộng ViewPatterns
.
Prelude> :set -XViewPatterns
Prelude> let f (last -> x) = x*2
Prelude> f [1, 2, 3]
6
Lưu ý rằng mô hình này sẽ luôn thành công, tuy nhiên, rất có thể bạn sẽ muốn thêm một mô hình cho trường hợp danh sách là rỗng, khác last
sẽ ném một ngoại lệ.
Prelude> f []
*** Exception: Prelude.last: empty list
Cũng lưu ý rằng đây chỉ là cú pháp. Không giống như đối sánh mẫu bình thường, đây là O (n), vì bạn vẫn đang truy cập phần tử cuối cùng của danh sách được liên kết đơn lẻ. Nếu bạn cần truy cập hiệu quả hơn, hãy xem xét sử dụng cấu trúc dữ liệu khác như Data.Sequence
, cung cấp quyền truy cập O (1) cho cả hai đầu.
Bạn có thể sử dụng ViewPatterns
để làm mô hình kết hợp vào cuối danh sách, vì vậy chúng ta hãy làm
{-# LANGUAGE ViewPatterns #-}
và sử dụng reverse
như viewFunction, bởi vì nó luôn luôn thành công, ví dụ như vậy
printLast :: Show a => IO()
printLast (reverse -> (x:_)) = print x
printLast _ = putStrLn "Sorry, there wasn't a last element to print."
Điều này là an toàn theo nghĩa là nó không ném bất kỳ ngoại lệ nào miễn là bạn bao trả tất cả các khả năng. (Bạn có thể viết lại nó để trả lại một Maybe
, ví dụ.)
Cú pháp
mainFunction (viewFunction -> pattern) = resultExpression
là cú pháp đường cho
mainFunction x = case viewFunction x of pattern -> resultExpression
để bạn có thể nhìn thấy nó thực sự chỉ đảo ngược danh sách rồi mẫu khớp với, nhưng nó đẹp hơn. viewFunction
chỉ là bất kỳ chức năng nào bạn thích. (Một trong những mục tiêu của phần mở rộng là để cho phép mọi người sạch sẽ và dễ dàng sử dụng các chức năng accessor cho phù hợp với mô hình để họ không cần phải sử dụng cấu trúc cơ bản của kiểu dữ liệu của họ khi quy định chức năng trên đó.)
Các câu trả lời khác giải thích các giải pháp dựa trên ViewPatterns
. Nếu bạn muốn làm cho nó nhiều mô hình kết hợp giống như, bạn có thể gói đó vào một PatternSynonym
:
tailLast :: [a] -> Maybe ([a], a)
tailLast [email protected](_:_) = Just (init xs, last xs)
tailLast _ = Nothing
pattern Split x1 xs xn = x1 : (tailLast -> Just (xs, xn))
và sau đó viết chức năng của bạn như ví dụ
foo :: [a] -> (a, [a], a)
foo (Split head mid last) = (head, mid, last)
foo _ = error "foo: empty list"
Đây là ngày đầu tiên lập trình Haskell và tôi cũng gặp phải vấn đề tương tự nhưng tôi không thể giải quyết sử dụng một số loại tạo tác bên ngoài như được đề xuất trong các giải pháp trước.
Cảm giác của tôi về Haskell là nếu ngôn ngữ cốt lõi không có giải pháp cho vấn đề của bạn, thì giải pháp là chuyển đổi vấn đề của bạn cho đến khi nó hoạt động cho ngôn ngữ.
Trong trường hợp này việc chuyển đổi vấn đề có nghĩa là chuyển đổi vấn đề đuôi thành vấn đề đầu, có vẻ như thao tác được hỗ trợ duy nhất trong khớp mẫu. Bạn có thể dễ dàng làm điều đó bằng cách sử dụng danh sách đảo ngược, sau đó làm việc trên danh sách được đảo ngược bằng cách sử dụng phần tử đầu như bạn sử dụng phần tử đuôi trong danh sách gốc và cuối cùng, nếu cần, hoàn nguyên kết quả về thứ tự ban đầu (ví dụ: nếu đó là một danh sách). Ví dụ, được đưa ra một danh sách các số nguyên (ví dụ: [1,2,3,4,5,6]), giả sử chúng ta muốn xây dựng danh sách này trong đó mỗi phần tử thứ hai của danh sách ban đầu bắt đầu từ phần cuối được thay thế bằng đôi của nó (tập thể dục lấy từ Homework1 của this excellent introduction to Haskell): [2,2,6,4,10,6].
Sau đó, chúng ta có thể sử dụng như sau:
revert :: [Integer] -> [Integer]
revert [] = []
revert (x:[]) = [x]
revert (x:xs) = (revert xs) ++ [x]
doubleSecond :: [Integer] -> [Integer]
doubleSecond [] = []
doubleSecond (x:[]) = [x]
doubleSecond (x:y:xs) = (x:2*y : (doubleSecond xs))
doubleBeforeLast :: [Integer] -> [Integer]
doubleBeforeLast l = (revert (doubleSecond (revert l)))
main = putStrLn (show (doubleBeforeLast [1,2,3,4,5,6,7,8,9]))
Đó rõ ràng là lâu hơn so với các giải pháp trước đó, nhưng nó cảm thấy hơn Haskell-ish với tôi.
Chào mừng bạn đến với StackOverflow và chúc mừng cho một khởi đầu tốt đẹp như vậy! Đảo ngược danh sách để truy cập vào cuối xa thực sự là một giải pháp rất Haskellish (mặc dù nó khá kém hiệu quả, nhưng việc sử dụng 'last' có thể tồi tệ hơn nếu bạn cần làm nhiều lần ... nếu hiệu suất là rất quan trọng và bạn cần truy cập một phần tử cuối cùng, thì danh sách không phải là một loại phù hợp). – leftaroundabout
Cảm ơn. Ở cấp độ tân binh của tôi, tôi thực sự quan tâm hơn đến việc khám phá các thành ngữ lập trình Haskell, hơn là tìm hiểu về tác động hiệu suất của chúng. Tôi đồng ý nó chắc chắn là một trường hợp tồi tệ hơn để cố gắng sử dụng một danh sách đơn giản liên kết theo thứ tự ngược lại và tôi đoán đây thực sự là lý do tại sao Haskell không cung cấp phù hợp với mô hình đuôi lúc đầu tiên. (Danh sách Haskell được thực hiện bằng cách sử dụng danh sách được liên kết đơn giản, đúng không?) – OlivierD
Đúng. Các danh sách Haskell rất tuyệt vời như các ngăn xếp, hoặc là các luồng vô tận, nhưng chúng thực sự tồi tệ khi truy cập ngẫu nhiên và việc truy cập vào đầu cuối không tốt hơn là truy cập bất kỳ phần tử nào ở giữa. – leftaroundabout
- 1. ASP.NET MVC Mẫu danh sách ràng buộc
- 2. Bạn có thể tạo mẫu đối sánh trên một tham số kiểu lớp bị ràng buộc không?
- 3. Scala Lấy các yếu tố đầu tiên và cuối cùng của Danh sách bằng cách sử dụng Ghép mẫu
- 4. Xóa các phần tử khỏi danh sách ràng buộc
- 5. Làm thế nào để bạn ràng buộc trẻ em của một mạng lưới vào danh sách?
- 6. Làm cách nào để kiểm tra phần tử cuối cùng của danh sách python?
- 7. C# combobox ràng buộc vào danh sách các đối tượng
- 8. Ràng buộc danh sách có thể chỉnh sửa của trẻ em
- 9. Bạn có thể sử dụng OleDbConnections với thành phần Script?
- 10. Danh sách ràng buộc các danh sách trong XAML?
- 11. GWT Danh sách biên tập ràng buộc
- 12. Ràng buộc Guice cho Danh sách các đối tượng chung
- 13. Windsor có thể tiêm danh sách các thành phần không?
- 14. Cách chèn phần tử vào danh sách cuối cùng?
- 15. Bạn có thể sử dụng Lambda trong danh sách khởi tạo của lớp không?
- 16. Sử dụng LaTeX, làm cách nào để có danh sách tham chiếu ở cuối mỗi phần?
- 17. Ràng buộc chung để đối sánh với các loại số
- 18. Danh sách ràng buộc với GridView
- 19. SQLite: danh sách ràng buộc của các giá trị để "WHERE col IN (: PRM)"
- 20. Bạn có sử dụng thuộc tính 'vị trí' của phần tử 'địa chỉ' trong một ràng buộc cổng WSDL không?
- 21. Phương pháp cuối cùng có thể sử dụng Powermockito trong lớp bê tông không cuối cùng?
- 22. ComboBox có thể chỉnh sửa với giá trị ràng buộc không có trong danh sách
- 23. Sử dụng bản đồ với hai danh sách thay vì một danh sách. Bạn có thể làm tổ không?
- 24. Đối sánh với phần tử thứ n của danh sách trong Scala
- 25. danh sách đối sánh scala
- 26. Mở danh sách đối số bằng mẫu biến thể
- 27. Lỗi SQL: Mã định danh nhiều phần "tableName.ColumnName" không thể bị ràng buộc
- 28. Có cách nào để chọn mục cuối cùng của danh sách với CSS không?
- 29. Danh sách ràng buộc mùa xuân <Object> để biểu mẫu: hộp kiểm
- 30. asp.net ràng buộc một danh sách để một GridView
cuối cùng ném ngoại lệ vào danh sách trống. Tôi đang tìm cách để tránh xa cuối cùng, đầu, fst, snd. Các hàm không xử lý tốt danh sách trống. Ví dụ, ví dụ, cho phép (x: xs) = "abcdefg" là những gì tôi đang đề cập đến trong câu hỏi của mình. Đã hy vọng có một cách tiếp cận tương tự để có được phần tử cuối cùng, mà không sử dụng các hàm prelude không an toàn. –
@MichaelLitchard: Ví dụ, bạn có thể xác định hàm 'safeLast' trả về' Có thể', sau đó bạn có thể khớp mẫu hoặc có thể đảo ngược danh sách và sau đó sử dụng đối sánh mẫu bình thường. – hammar
vì nó luôn thành công, nó không phải là một "trận đấu mẫu" chút nào. 'f = (* 2). cuối cùng là tốt hơn. – u0b34a0f6ae