2012-01-01 34 views
7

Tôi mới sử dụng Haskell và tôi đang thử một vài hướng dẫn. tôi đã viết kịch bản này:Cách đúng để xác định chức năng trong Haskell

lucky::(Integral a)=> a-> String 
lucky 7 = "LUCKY NUMBER 7" 
lucky x = "Bad luck" 

tôi lưu này như lucky.hs và chạy nó trong người phiên dịch và nó hoạt động tốt.

Nhưng tôi không chắc chắn về định nghĩa chức năng. Có vẻ như từ nhỏ, tôi đã đọc mà tôi đều có thể xác định các chức năng may mắn như sau (tên hàm là lucky2):

lucky2::(Integral a)=> a-> String 
lucky2 x=(if x== 7 then "LUCKY NUMBER 7" else "Bad luck") 

Cả hai dường như làm việc tốt như nhau. Rõ ràng chức năng may mắn là rõ ràng hơn để đọc nhưng là lucky2 một cách chính xác để viết một chức năng?

+4

Theo như tôi biết, chúng giống nhau về ý nghĩa nhưng cái đầu tiên trông đẹp hơn và là cách ưu tiên để thực hiện nó trong Haskell. Tôi sẽ không đăng bài này như là một câu trả lời vì tôi không phải là một Haskell chuyên nghiệp và có thể là sai. – Matej

+0

Nhân tiện, bạn không cần ngoặc đơn: 'lucky2 x = if x == 7 rồi" SỐ LUCKY 7 "khác" Xấu may "' – sdcvvc

+0

Ngoài ra, bạn có thể viết kiểu như «lucky :: Integral -> String' . Các công cụ đặt tên ở bên trái của '=>' chỉ dành cho trường hợp bạn cần cùng một loại hai lần. –

Trả lời

14

Cả hai đều chính xác. Có thể cho rằng, cái đầu tiên là Haskell thành ngữ hơn vì nó sử dụng tính năng rất quan trọng của nó được gọi là mẫu phù hợp với. Ở dạng này, nó sẽ thường được viết là:

lucky::(Integral a)=> a-> String 
lucky 7 = "LUCKY NUMBER 7" 
lucky _ = "Bad luck" 

Các gạch nghĩa thực tế là bạn đang bỏ qua các hình thức chính xác (giá trị) của tham số của bạn. Bạn chỉ quan tâm rằng nó khác với 7, là mẫu được ghi lại bởi tuyên bố trước đó của bạn.


Tầm quan trọng của khớp mẫu được minh họa tốt nhất theo chức năng hoạt động trên dữ liệu phức tạp hơn, chẳng hạn như danh sách. Nếu bạn đã viết một hàm tính toán chiều dài của danh sách, ví dụ, bạn có thể sẽ bắt đầu bằng cách cung cấp một biến thể cho các danh sách rỗng:

len [] = 0 

Mệnh [] là một mô hình, được thiết lập để phù hợp với danh mục sản phẩm nào . Danh sách trống rõ ràng có độ dài là 0, vì vậy đó là những gì chúng tôi đang có chức năng của chúng tôi trở lại.

Các phần khác của len sẽ là như sau:

len (x:xs) = 1 + len xs 

Ở đây, bạn đang so khớp trên mô hình (x:xs). Colon : là cái gọi là toán tử số: nó đang thêm một giá trị vào danh sách. Do đó, một biểu thức x:xs là một mẫu phù hợp với một số phần tử (x) được thêm vào một số danh sách (xs). Nói chung, nó khớp với danh sách có ít nhất một phần tử, vì xs cũng có thể là danh sách trống ([]).

Định nghĩa thứ hai này là len cũng khá đơn giản. Bạn tính toán độ dài của danh sách còn lại (len xs) và ở mức 1, tương ứng với phần tử đầu tiên (x).

(Cách thông thường để viết định nghĩa trên sẽ là:

len (_:xs) = 1 + len xs 

mà một lần nữa thể hiện rằng bạn không quan tâm những gì các yếu tố đầu tiên là, duy nhất mà nó tồn tại).

+0

Thật không may, bạn chứng minh một cách xấu cho độ dài danh sách máy tính. – Ingo

+5

Ingo, wut? Ngay cả std. thư viện thực hiện theo cách này: [genericLength] (http://www.haskell.org/ghc/docs/latest/html/libraries/base/src/Data-List.html#genericLength). Bạn có thể làm tối ưu hóa cho 'Int' và một số loại khác, chắc chắn (xem 'strictGenericLength'), nhưng nó thậm chí không thay đổi các yêu cầu thời gian tiệm cận. – Rotsor

7

Một cách thứ 3 để viết những dòng này sẽ được sử dụng bảo vệ:

lucky n 
    | n == 7 = "lucky" 
    | otherwise = "unlucky" 

Không có lý do gì để bị nhầm lẫn về điều đó. Luôn luôn có nhiều hơn 1 cách để làm điều đó. Lưu ý rằng điều này sẽ đúng ngay cả khi không có kết hợp mẫu hoặc bảo vệ và bạn để sử dụng if.

Tất cả các biểu mẫu mà chúng tôi đã đề cập cho đến nay đều sử dụng cái gọi là đường cú pháp do Haskell cung cấp. Bảo vệ mẫu được chuyển thành các biểu thức trường hợp thông thường, cũng như nhiều mệnh đề hàm và nếu các biểu thức. Do đó ở mức độ thấp nhất, cách unsugared viết này sẽ là lẽ:

lucky n = case n of 
    7 -> "lucky" 
    _ -> "unlucky" 

Trong khi nó là tốt bạn nên kiểm tra cách thành ngữ tôi khuyên bạn nên để một người mới bắt đầu mà ông sử dụng bất cứ điều gì làm cho anh ta tốt nhất, bất cứ điều gì anh ấy hiểu rõ nhất. Ví dụ, nếu một trong những (chưa) hiểu điểm phong cách tự do, không có lý do để buộc nó. Nó sẽ đến với bạn sớm hay muộn.

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