2010-01-09 41 views
12

Tôi là một chàng trai C# đang cố gắng tự mình dạy Haskell từ các webcast trên Kênh 9 của Erik Meijer. Tôi bắt gặp một câu đố thú vị liên quan đến việc bỏ qua mọi thành phần 'n' của danh sách bằng cách sử dụng zip và mod.Làm thế nào để tạo danh sách lặp lại vô hạn trong Haskell?

every :: Int -> [a] -> [a] 
every _ [] = [] 
every n xs = [x | (x,i) <- zip xs [1..], i `mod` n == 0] 

Tôi đã nghĩ rằng nó có thể hiệu quả hơn (đối với danh sách hoặc luồng thực sự lớn) nếu chúng tôi có thể tránh sử dụng mod.

Tôi nghĩ về việc tạo ra một danh sách các số nguyên lặp đi lặp lại để chúng ta có thể so sánh giá trị của i với n.

repeatInts :: Int -> [Int] 

như vậy gọi repeatInts 3 lợi nhuận [1,2,3,1,2,3,1,2,3,1,2,3,..] vô cùng tận.

Vì điều này, chúng ta có thể xác định lại every như vậy:

every :: Int -> [a] -> [a] 
every _ [] = [] 
every n xs = [x | (x,i) <- zip xs (repeatInts n), i == n] 

Vì vậy, câu hỏi của tôi là: làm thế nào bạn sẽ thực hiện repeatInts?

+0

Cf. http://stackoverflow.com/questions/2026912/how-to-get-every-nth-element-of-an-infinite-list-in-haskell –

Trả lời

17

Sử dụng cycle:

cycle :: [a] -> [a] 

cycle quan hệ một danh sách hữu hạn thành một hình tròn, hoặc tương đương, sự lặp lại vô hạn của danh sách gốc. Đó là danh tính trên danh sách vô hạn.

Bạn có thể xác định repeatInts về cycle:

*Main> let repeatInts n = cycle [1..n] 
*Main> :t repeatInts 
repeatInts :: (Num t, Enum t) => t -> [t] 
*Main> take 10 $ repeatInts 3 
[1,2,3,1,2,3,1,2,3,1] 

Đối với người hiếu, GHC thực hiện cycle với

cycle [] = errorEmptyList "cycle" 
cycle xs = xs' where xs' = xs ++ xs' 

Trong cách nói hoàn toàn chức năng, kỹ thuật tò mò này là biết dưới dạng buộc nút, một d nó tạo ra các cấu trúc dữ liệu tuần hoàn thay vì các cấu trúc vô hạn.

Để biết chi tiết thấy

+0

Cảm ơn, gbacon. Bằng cách nào đó tôi biết sẽ có một câu trả lời đơn giản! Bây giờ tôi có thể đào sâu vào các hoạt động của 'chu kỳ'. –

+0

Hơi lạ, 'chu kỳ' là tiêu chuẩn Haskell '98, mặc dù danh sách tuần hoàn không. Xem những gì các nguồn (ở trên) nói về nó - bạn có thể hoặc có thể không nhận được một danh sách cyclic ... –

+1

funnily, Q/A này chính nó là một ví dụ của vấn đề XY. ;) bỏ qua mọi phần tử thứ n trong danh sách không nên liên quan đến bất kỳ 'mod' nào, cũng không tính đến vô hạn. giải pháp thích hợp có vẻ là với 'zip' với' (chu kỳ $ (0 <$ [2..n]) ++ [1]) ', hoặc thông qua' iterate' với 'splitAt'. :) –

2

câu trả lời cuối nhưng nó cũng có thể được viết như t của anh ấy:

repeatInts :: Int -> [Int] 
repeatInts 0 = [] 
repeatInts a = [1..a] ++ repeatInts a 
Các vấn đề liên quan