2010-09-20 32 views
50

Khi đọc Wikipedia's entry on Haskell 2010 tôi stumbled trên này:Mẫu "n + k" là gì và tại sao chúng bị cấm sử dụng Haskell 2010?

-- using only prefix notation and n+k-patterns (no longer allowed in Haskell 2010) 
factorial 0 = 1 
factorial (n+1) = (*) (n+1) (factorial n) 

sao họ có ý nghĩa gì bởi "n + k mẫu"? Tôi đoán đó là dòng thứ hai, nhưng tôi không hiểu điều gì có thể sai với nó. Bất cứ ai có thể giải thích vấn đề là gì? Tại sao các mẫu n + k này không được phép sử dụng trong Haskell 2010?

+0

cho một gợi ý có lẽ là * lý do * của mẫu n + k kiểm tra bài đăng trên blog tuyệt vời này: http://blog.sigfpe.com/2007/07/data-and-codata.html – jberryman

+6

Đối với những người vẫn còn muốn sử dụng mẫu n + k (tôi đang nhìn bạn, Erik Meijer), có '-XNPlusKPatterns' hoặc' {- # LANGUAGE NPlusKPatterns # -} ' – tlo

Trả lời

58

Mẫu n + k là gì? Hãy ngây ngô lúc này:

$ ghci 
GHCi, version 6.12.3: http://www.haskell.org/ghc/ :? for help 
Loading package ghc-prim ... linking ... done. 
Loading package integer-gmp ... linking ... done. 
Loading package base ... linking ... done. 
Loading package ffi-1.0 ... linking ... done. 
Prelude> let f 0 = 0 ; f (n+5) = n 
Prelude> :t f 
f :: (Integral t) => t -> t 
Prelude> f 0 
0 
Prelude> f 1 
*** Exception: <interactive>:1:4-24: Non-exhaustive patterns in function f 

Prelude> f 2 
*** Exception: <interactive>:1:4-24: Non-exhaustive patterns in function f 

Prelude> f 3 
*** Exception: <interactive>:1:4-24: Non-exhaustive patterns in function f 

Prelude> f 4 
*** Exception: <interactive>:1:4-24: Non-exhaustive patterns in function f 

Prelude> f 5 
0 
Prelude> f 6 
1 

Họ cơ bản là một trường hợp vô cùng đặc biệt đối với mô hình kết hợp mà chỉ làm việc trên con số và đó làm ... tốt, chúng ta hãy chỉ tỏ ra lịch sự và gọi nó là "điều bất ngờ" đối với những số.

Ở đây tôi có chức năng f có hai mệnh đề. Mệnh đề đầu tiên khớp với 0 và chỉ 0. Mệnh đề thứ hai khớp với bất kỳ giá trị nào của kiểu Integral có giá trị là 5 hoặc lớn hơn. Tên bị ràng buộc (n, trong trường hợp này) có giá trị bằng với số bạn đã chuyển trong dấu trừ 5. Vì lý do chúng bị xóa khỏi Haskell 2010, tôi hy vọng bạn có thể thấy lý do ngay bây giờ chỉ với một chút suy nghĩ. (Gợi ý: xem xét các "nguyên tắc tối thiểu ngạc nhiên" và làm thế nào nó có thể hoặc không thể áp dụng ở đây.)


Edited thêm:

Một câu hỏi tự nhiên nảy sinh bây giờ mà các cấu trúc bị cấm là "bạn sử dụng cái gì để thay thế chúng?"

$ ghci 
GHCi, version 6.12.3: http://www.haskell.org/ghc/ :? for help 
Loading package ghc-prim ... linking ... done. 
Loading package integer-gmp ... linking ... done. 
Loading package base ... linking ... done. 
Loading package ffi-1.0 ... linking ... done. 
Prelude> let f 0 = 0 ; f n | n >= 5 = n - 5 
Prelude> :t f 
f :: (Num t, Ord t) => t -> t 
Prelude> f 0 
0 
Prelude> f 1 
*** Exception: <interactive>:1:4-33: Non-exhaustive patterns in function f 

Prelude> f 2 
*** Exception: <interactive>:1:4-33: Non-exhaustive patterns in function f 

Prelude> f 3 
*** Exception: <interactive>:1:4-33: Non-exhaustive patterns in function f 

Prelude> f 4 
*** Exception: <interactive>:1:4-33: Non-exhaustive patterns in function f 

Prelude> f 5 
0 
Prelude> f 6 
1 

Bạn sẽ nhận thấy từ các câu lệnh loại không chính xác như nhau, nhưng việc sử dụng bảo vệ là "đủ". Việc sử dụng các n-5 trong biểu thức có thể nhận được tẻ nhạt và dễ bị lỗi trong bất kỳ mã nào sử dụng nó ở nhiều nơi. Câu trả lời sẽ được sử dụng một điều khoản where dọc theo dòng này:

Prelude> let f 0 = 0 ; f n | n >= 5 = n' where n' = n - 5 
Prelude> :t f 
f :: (Num t, Ord t) => t -> t 
Prelude> f 0 
0 
Prelude> f 5 
0 
Prelude> f 6 
1 

Mệnh where phép bạn sử dụng biểu thức tính toán ở nhiều nơi mà không có nguy cơ đánh nhầm. Vẫn còn khó chịu khi phải chỉnh sửa giá trị biên giới (5 trong trường hợp này) ở hai vị trí riêng biệt trong định nghĩa hàm, nhưng cá nhân tôi cảm thấy đây là một mức giá nhỏ để trả cho sự gia tăng hiểu biết về nhận thức.


Tiếp tục chỉnh sửa để thêm:

Nếu bạn thích let biểu trên where khoản, đây là một sự thay thế:

Prelude> let f 0 = 0 ; f n | n >= 5 = let n' = n - 5 in n' 
Prelude> :t f 
f :: (Num t, Ord t) => t -> t 
Prelude> f 0 
0 
Prelude> f 5 
0 

Và đó là nó. Tôi thực sự đã xong rồi.

+1

+2 (có hai) Phiếu bầu của tôi đi đến câu trả lời bởi vì nó được giải thích một cách tuyệt vời với 'cái gì đó' và 'tại sao nó' được bao phủ hoàn toàn. –

+0

Tuyệt vời! Cảm ơn!! –

+0

Câu trả lời hay! Tôi khá mới với Haskell nên câu hỏi tiếp theo của tôi là: tại sao bộ kiểm tra kiểu cho phép mẫu đó và không đưa ra ít nhất một cảnh báo? Trong trường hợp này, nó phải biết rằng mã đó thiếu một số trường hợp. – futtetennista

4

Liên kết được cung cấp bởi trinithis là chính xác; Các mẫu n + k không còn được bao gồm trong thông số kỹ thuật của Haskell.

Để biết thêm thông tin cơ bản về mẫu n + k nói chung, hãy cuộn khoảng 3/5 đường xuống trang này trên pattern matching hoặc xem ngắn post này.

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