2013-03-14 31 views
7

Giả sử tôi có một chức năng thực hiện một số tính toán, với một số mẫu; được thực hiện dưới hình thức khớp mẫu.Haskell có cho phép biểu thức cho phép đối sánh nhiều mẫu không?

Hầu hết các mẫu này (cùng với những thứ khác khác nhau) một cách xử lý thông số, mà tôi sử dụng biến trung gian trong biểu thức let. Nhưng tôi thấy nó thực sự dư thừa để có cùng một let trên nhiều mẫu, và tôi tự hỏi nếu có một cách để xác định một let cho một số mẫu?

Dưới đây là một ví dụ về nhân đôi của tôi let:

data MyType a = Something a | Another Int [a] 

myFunc (Something x) = -- return something, this isn't the point here 
myFunc (Another 0 xs) = 
    let intermediary = some $ treatment xs 
    in doSthg intermediary 1 
myFunc (Another 1 (x:xs)) = 
    let intermediary = some $ treatment xs 
    in doSthg1 intermediary 1 x 
myFunc (Another 2 (x:x':xs)) = 
    let intermediary = some $ treatment xs 
    in doSthg2 intermediary 2 x x' 

Bạn có thể thấy rằng các tham số xs luôn luôn hiện diện khi tôi sử dụng nó cho intermediary, và điều này có thể được factorised. Nó có thể dễ dàng đạt được bằng cách sử dụng một chức năng trợ giúp nhưng tôi đã tự hỏi nếu những gì tôi yêu cầu là có thể mà không có một. Hãy cố gắng giữ cho nó đơn giản cho người mới bắt đầu, và tôi hy vọng ví dụ của tôi là đủ rõ ràng.

+2

Không! Gotta sử dụng một chức năng riêng biệt và vượt qua nó như là một tham số một cách rõ ràng để yếu tố ra lặp đi lặp lại mã. Theo như Haskell có liên quan, sự xuất hiện ở trên của 'xs' là các biến hoàn toàn khác nhau (vì chúng có các vị trí liên kết khác nhau). – luqui

+0

Cảm ơn! Bây giờ tôi có một câu hỏi khác: bạn có dự định rằng các phương trình thứ ba và thứ tư không bao giờ khớp? Bởi vì 'xs' khớp với bất kỳ danh sách nào ... Bạn đã đảo ngược thứ tự các phương trình? – yatima2975

+0

Tôi đã viết điều này để minh họa rằng 'xs' được trích xuất từ ​​kết hợp mẫu trong nhiều mẫu nhưng không phải lúc nào cũng có cùng ý nghĩa (nếu không khớp mẫu sẽ không quan tâm: chỉ có một mẫu). Những gì được thực hiện với nó trong ví dụ này không quan trọng; nhưng trong mã của tôi 'y' được thay thế bằng các giá trị thực để các mẫu sau đó khớp nhau. Nhưng bạn nói đúng một lần nữa vì vậy tôi sẽ chỉnh sửa nó với một loại cụ thể để làm cho toàn bộ điều dễ hiểu hơn. –

Trả lời

7

này đặc biệt vấn đề có thể được làm việc xung quanh như sau:

myFunc2 (Something x) = returnSomething x 
myFunc2 (Another n ys) = 
    let xs = drop n ys 
     x = head ys 
     x' = head (tail ys) 
     intermediate = some $ treatment xs 
    in case n of 
     0 -> doSomething intermediate n 
     1 -> doSomething1 intermediate n x 
     2 -> doSomething2 intermediate n x x' 

Nhờ đánh giá lười biếng xx' sẽ chỉ đánh giá nếu giá trị của họ là cần thiết.

Tuy nhiên - và đây là một tuy nhiên lớn! - mã của bạn sẽ cung cấp lỗi thời gian chạy khi bạn cố gắng gọi myFunc2 (Another 2 []) (và nếu doSomething2 thực sự sử dụng x!) vì để tìm hiểu xem x là gì, chúng tôi cần đánh giá head ys - và điều đó sẽ sụp đổ cho danh sách trống. Mã bạn đưa ra làm ví dụ cũng sẽ không hoạt động (một lỗi thời gian chạy khác) cho Another 2 [] vì không có mẫu phù hợp, nhưng sẽ dễ dàng hơn trong việc cung cấp trường hợp dự phòng.

Điều này có thể không thành vấn đề nếu bạn kiểm soát đầu vào và luôn đảm bảo rằng danh sách trong Another đủ dài, nhưng điều quan trọng là phải biết vấn đề này!

+0

Đây không phải là vấn đề trong mã của tôi vì các đối tượng 'Khác' không thể được xây dựng với danh sách trống. 1, nó thực hiện thủ thuật rất tốt –

+0

@tehinternetsismadeofcatz: Toàn bộ vấn đề là một "thông dịch viên cho một ngôn ngữ ngăn xếp" mạnh mẽ, vì vậy nếu bạn biên dịch đúng, bạn sẽ chạy đúng - hệ thống kiểu chỉ là không (nhưng nó gần!) đủ mạnh để thể hiện những gì bạn biết * về đầu vào. Bạn cũng có thể cân nhắc việc thay đổi 'MyType' để diễn đạt những điều bạn biết về các đối số rõ ràng hơn, nhưng đó là rất nhiều công việc ... – yatima2975

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