2012-01-05 35 views
22

tôi nhận thấy ngày nay rằng đó là một định nghĩaĐịnh nghĩa một hàm bằng phương trình với số lượng khác nhau của các đối số

là không thể. Tôi chỉ tò mò những gì (tốt) lý do đằng sau này là. Có phải là một trong rất tốt (đó là Haskell sau khi tất cả :)).

Lưu ý: Tôi không tìm kiếm đề xuất cho các triển khai thay thế cho mã ở trên, đó là ví dụ đơn giản để chứng minh quan điểm của tôi.

+4

Bạn gọi là "an toàn"? Hãy để nó trả về một 'Có thể' hoặc một cái gì đó, hoặc ném một số ngoại lệ đã biết hoặc sử dụng nó trên một' newtype' dành riêng cho các hàm không thoái hóa mà bạn coi là thành viên của ví dụ. không gian Hilbert L² (tức là chỉ được định nghĩa các bộ null); điều đó sẽ an toàn. Chỉ cần xác định 'x/0 = x' _ad hoc_ cho tất cả các trường hợp' Fractional' là vô cùng phi lý! - Vâng, nó có lẽ chỉ có nghĩa là một ví dụ. – leftaroundabout

+0

+1 Wow, được sử dụng Haskell trong nhiều năm và không bao giờ nhận thấy rằng định nghĩa như vậy là không được phép! – is7s

+0

@leftaroundabout 'safeDivide x 0 = Không có gì; safeDivide = Chỉ.: (/) 'tốt hơn? :) –

Trả lời

25

Tôi nghĩ rằng đó là chủ yếu cho sự nhất quán để tất cả các mệnh đề có thể được đọc theo cách tương tự, do đó, để nói chuyện; tức là mọi RHS đều có cùng vị trí trong loại chức năng. Tôi nghĩ rằng sẽ che giấu khá một vài lỗi ngớ ngẩn nếu bạn cho phép điều này, quá.

Ngoài ra còn có một quirk ngữ nghĩa nhẹ: nói rằng trình biên dịch đưa ra các mệnh đề như vậy để có cùng số mẫu như các mệnh đề khác; ví dụ: ví dụ của bạn sẽ trở thành

safeDivide x 0 = x 
safeDivide x y = (/) x y 

Bây giờ, hãy xem xét nếu dòng thứ hai thay vì là safeDivide = undefined; trong trường hợp không có điều khoản trước đó, safeDivide sẽ là , nhưng nhờ vào việc mở rộng eta được thực hiện tại đây, nó là \x y -> if y == 0 then x else ⊥ - vì vậy safeDivide = undefined không thực sự xác định safeDivide! Điều này có vẻ khó hiểu, đủ để biện minh cho việc cấm các điều khoản như vậy, IMO.

+0

Vì vậy, không có lý do kỹ thuật sâu sắc hơn? – aelguindy

+1

@aelguindy: Thật ra, vâng! Tôi đã cập nhật câu trả lời của tôi :) – ehird

+0

Cảm ơn bạn đã chỉnh sửa định dạng mã :), sẽ thực hiện điều đó từ bây giờ. Phải mất một thời gian để có được lý do tại sao nó const (const \ bot), nhưng bây giờ tôi nhận được nó. – aelguindy

11

Ý nghĩa của một hàm với nhiều điều khoản được xác định bởi các tiêu chuẩn Haskell (section 4.4.3.1) qua dịch để một lambda và case tuyên bố:

fn pat1a pat1b = r1 
fn pat2a pat2b = r2 

trở thành

fn = \a b -> case (a,b) of 
    (pat1a, pat1b) -> r1 
    (pat2a, pat2b) -> r2 

Điều này là để định nghĩa hàm/trường hợp tuyên bố cách làm việc là tốt đẹp và nhất quán, và ý nghĩa của từng không được quy định một cách dư thừa và gây nhầm lẫn.

Bản dịch này chỉ thực sự có ý nghĩa khi mỗi mệnh đề có cùng số đối số. Tất nhiên, có thể có thêm các quy tắc để khắc phục điều đó, nhưng họ sẽ làm phức tạp bản dịch cho ít được, vì có thể bạn sẽ không muốn định nghĩa những thứ như thế, vì lợi ích của độc giả.

4

Haskell thực hiện theo cách này bởi vì đó là người tiền nhiệm (như LML và Miranda) đã làm. Không có lí do kỹ thuật nào nó phải như thế này; các phương trình có ít đối số hơn có thể được mở rộng. Nhưng có một số khác nhau của các đối số cho phương trình khác nhau có lẽ là một lỗi đánh máy hơn là cố ý, vì vậy trong trường hợp này chúng tôi cấm một cái gì đó hợp lý & hiếm để có được báo cáo lỗi tốt hơn trong trường hợp phổ biến.

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