2013-02-22 34 views
7

Tôi không hiểu tại sao hai comprehensions danh sách tương tự cho kết quả khác nhau:tương tự Haskell danh sách comprehensions với kết quả khác nhau

Prelude> let t2s n= [ 1/(2*i) | i <- [1,3..n]] 
Prelude> t2s 0 
[0.5] 
Prelude> let t2s n= [ (2*i) | i <- [1,3..n]] 
Prelude> t2s 0 
[] 

tôi mong đợi cả hai trở về [] trên lập luận 0. Tôi phải thiếu một cái gì đó ngớ ngẩn ?!

Trả lời

6

Nó đã làm với thực tế là

enumFromThenTo 1.0 3.0 0.0 

đánh giá để [1.0]. Bạn có thể tìm thấy thông số kỹ thuật của enumFromThenTo cho Floats trong phần 6.3.4 của http://www.haskell.org/onlinereport/haskell2010/haskellch6.html.

+2

Để tăng phao, [a, b..c] tiếp tục cho đến khi các số vượt quá c + (b-a) /2.0. Ví dụ [1.0, 2.0 .. 4.0] là [1.0, 3.0, 5.0]. –

+0

Điều gì đã xảy ra với 2.0 và 4.0 trong ví dụ của bạn? –

+0

@ Code-Guru. Mea culpa. Ý tôi là [1.0, 3.0 .. 4.0]. Cảm ơn. –

7

Trước hết, tôi đã thay đổi tên của t2s thành t1s đầu tiên của bạn, để tôi có thể có cả hai được tải vào ghci cùng một lúc. Nhìn vào các loại suy ra cho mỗi người trong số họ:

[ts.hs:2:1-33] *Main> :t t1s 
t1s :: (Enum t, Fractional t) => t -> [t] 
[ts.hs:2:1-33] *Main> :t t2s 
t2s :: (Enum t, Num t) => t -> [t] 
[ts.hs:2:1-33] *Main> 

Lưu ý rằng t1s nhận một đối số Fractional trong khi t2s mất một Num. Điều này có nghĩa là trong t1s 0, số 0 được phỏng đoán là Double. Mặt khác, thông dịch viên sẽ nhập 0 vào số Integer trong t2s 0. Vì loại được sử dụng cho đối số khác nhau, hành vi có thể khác nhau theo những cách rất đáng ngạc nhiên. Cụ thể, bạn nên đảm bảo chỉ sử dụng các loại Integral khi liệt kê một danh sách như trong [1,3..n].

Để khắc phục điều này, bạn chỉ cần cung cấp chữ ký loại rõ ràng cho cả hai chức năng.

+3

Cảnh cáo mặc định một lần nữa! Về cơ bản, suy luận kiểu tìm loại chung nhất. Vấn đề là các chữ số được quá tải, do đó, một biểu thức như 't2s 0' không rõ ràng - nó có thể hợp lệ đối với * bất kỳ * kiểu số nào! Vì sự mơ hồ như thế này là phổ biến và chúng tôi muốn có thể sử dụng Haskell như một máy tính, chúng tôi có một cách hacky để đối phó với nó: [defaulting] (http://www.haskell.org/onlinereport/decls.html#sect4 .3.4). Về cơ bản, trước tiên chúng ta thử 'Integer' và sau đó thử' Double' cho các biểu thức như thế này. Bạn có thể muốn chỉnh sửa một cái gì đó về điều này vào câu trả lời của bạn. –

+0

@TikhonJelvis Tôi là một newb Haskell và không biết về việc mặc định cho đến khi bạn đăng nhận xét này. Câu trả lời của tôi được đăng ở đây đơn giản đến từ việc hack vào mã OP vì tôi cũng tò mò về sự khác biệt. Tôi đã tìm thấy sự khác biệt về loại khi tôi ': bước qua quá trình đánh giá. –

+0

Đó là thời điểm tốt để tìm hiểu về nó như bất kỳ :). Tôi thực sự lần đầu tiên đọc về nó khi trả lời một câu hỏi SO quá. Trong thực tế, đó là cách tôi đã nhặt được một loạt các mẩu tin như vậy. –

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