2012-03-30 8 views
5

tôi phải xác định một danh sách trong đó:Haskell, xác định danh sách vô hạn, thêm dữ liệu khi đang di chuyển và sắp xếp cùng một lúc. Làm sao?

  • 1 là thành viên
  • nếu n là thành viên, vì vậy là 2n + 1 và 3n + 1

Vì vậy, danh sách là vô hạn và phải được sắp xếp. Khi nạp vào GHCi, lệnh:

"take 10 theList" 

sẽ sản xuất:

[1,3,4,7,9,10,13,15,19,21] 

Dưới đây là mã của tôi:

theList = ([1] ++ concat [[(x*2+1),(x*3+1)]|x<-theList]) 

Có vẻ như để làm việc trừ rằng nó không phải được sắp xếp, các cùng một lệnh như trên tạo ra:

[1,3,4,7,10,9,13,15,22,21] 

Có ai có ý tưởng nào để phân loại nó không? Cảm ơn

+5

Chức năng 'allInOne' của bạn chính xác là [' concat'] (http://hackage.haskell.org/packages/archive/base/latest/doc/html/Prelude.html#v:concat). Haskell có nhiều chức năng "tích hợp sẵn" mà bạn có thể tìm kiếm bằng chữ ký loại bằng cách sử dụng [Hoogle] (http://www.haskell.org/hoogle/) (đây là một trong những công cụ làm cho Haskell tuyệt vời!), Ví dụ: 'allInOne' có loại' [[a]] -> [a] 'và [kết quả đầu tiên] (http: //www.haskell.org/hoogle/? hoogle = \ [\ [a \] \] + - % 3E + \ [a \]) là cái bạn đang tìm kiếm. :) – huon

+1

Có một triển khai tự nhiên tốt đẹp liên quan đến _corecursion_. Theo cách nó giống với danh sách vô hạn các số Fibonacci: 'fibs = 0: 1: zipWith (+) fibs (tail fibs)'. Làm thế nào bạn sẽ mở rộng danh sách khi bạn đã có 'theList' của một số kích thước? – Vitus

Trả lời

7

Vấn đề có thể mặc dù như một cây nhị phân vô hạn (AB là nhãn cho các chi nhánh):

1__ B 
    | 4___ 
    | \ 13 ... 
A 3_ \ 
    | \ 9 ... 
    7 10 
    ... 

Suy nghĩ về nó theo cách này, chúng ta có thể thấy rằng chúng tôi muốn viết một chức năng ("listify") chuyển đổi "cây" thành danh sách được sắp xếp. Đây là nơi Haskell thực sự tốt đẹp: nếu chúng ta có một hàm (merge) cần hai danh sách được sắp xếp (vô hạn) và gộp chúng thành một danh sách được sắp xếp (bạn nên viết hàm này), sau đó listify -ing cây đơn giản là listify -ing hai chi nhánh, sáp nhập chúng và đặt gốc vào lúc bắt đầu, tức là trong cây trên

1:merge (listify A) (listify B) 

Vì đây là bài tập về nhà tôi sẽ không nói nhiều hơn, nhưng bất kỳ nhánh cây nào đều được xác định hoàn toàn bởi gốc nút, do đó, chữ ký loại listify có thể là Integer -> [Integer]. Và khi bạn có listify, thì theList = listify 1.

+0

Cảm ơn bạn. Tôi vừa thử, nhưng kể từ khi danh sách không được sắp xếp, không có cách nào để hợp nhất hoặc sắp xếp chúng. Nếu nó hoạt động, tôi sẽ chỉ phải đặt một hàm 'sắp xếp' khác trước định nghĩa danh sách. Vấn đề là, nếu tôi đã làm điều đó, và cố gắng 'mất 20 theList' Haskell sẽ sụp đổ (có nghĩa là nó đã không quay trở lại lệnh' Main> '. Tôi đoán tôi phải tạo danh sách khi đang di chuyển và sắp xếp nó ngay sau khi phần tử mới được đưa vào đó. Cách duy nhất tôi có thể nghĩ đến là: theList = [x | x <- [1 ..], thỏa mãn x] nơi thỏa mãn x ..... Nhưng tôi bị kẹt trong địa chỉ 'đáp ứng ' Định nghĩa. –

+1

Danh sách * được sắp xếp nếu bạn đã viết chính xác 'listify' và' merge' (điều này không hữu ích lắm). Haskell có thể bị lỗi bởi vì bạn đang tạo một vòng lặp vô hạn (có thể "' listify n' "xuất hiện ở phía bên tay phải của định nghĩa' listify n'? Hoặc tương tự trong 'merge'?). – huon

+1

Vấn đề với điều này là bản sao chỉ được xử lý ở bước hợp nhất, không phải trong quá trình tạo, theo thời gian, gây ra rất nhiều công việc không cần thiết. Nó tạo ra một định nghĩa rất ngắn gọn, khai báo mặc dù. –

4

Một cách khác để xem đây là danh sách các số nguyên được lọc. Số n là một phần của chuỗi nếu n = 1 (mod 2) và (n-1)/2 là một phần của chuỗi, hoặc nếu n = 1 (mod 3) và (n-1)/3 là một một phần của chuỗi.

+0

Cảm ơn câu trả lời của bạn, nhưng nó sẽ không hoạt động với số nguyên, như (6 - 1) 'mod' 3 = 1, nhưng 6 không nên có trong danh sách như bạn có thể thấy trong câu hỏi của tôi. Có một vấn đề làm tròn lớn ở đây. –

+0

@crazyfffan, tôi nghĩ rằng điều này không hoạt động: 6/= 1 (mod 3), do đó, nó thậm chí không được xem xét bởi các bộ phận. ('mod' và' div' là các hàm khác nhau) – huon