2010-02-03 17 views
22

khi bạn chia danh sách bằng cách sử dụng cú pháp x: xs tại sao nó được bao trong dấu ngoặc đơn? ý nghĩa của dấu ngoặc đơn là gì? tại sao không [x: xs] hoặc chỉ x: xs?Dấu ngoặc đơn biểu thị trong (x: xs) khi khớp mẫu là gì?

+0

Bạn có ví dụ về vị trí được gói trong() không? x: xs có thể được sử dụng để mô tả danh sách có phần tử đầu tiên của danh sách. [x: xs] sẽ là danh sách có danh sách x: xs trong đó. –

+0

Ông nói về sự phù hợp với mô hình, không phải về việc xây dựng danh sách. – Rorick

Trả lời

41

Các tế bào khuyết điểm không phải ngoặc trong mọi bối cảnh, nhưng trong hầu hết các tình huống đó là vì

ứng dụng Chức năng liên kết chặt chẽ hơn so với bất kỳ nhà điều hành ghi.

Đốt nó vào não của bạn bằng các chữ cái cháy.

Ví dụ:

length [] = 0 
length (x:xs) = 1 + length xs 

Nếu ngoặc đã được bỏ qua các trình biên dịch sẽ nghĩ rằng bạn đã có một cuộc tranh cãi x tiếp theo là một nhà điều hành ghi ill-đặt, và nó sẽ phàn nàn cay đắng. Mặt khác đây là OK

length l = case l of [] -> 0 
        x:xs -> 1 + length xs 

Trong trường hợp này không phải x cũng không xs có thể có thể được hiểu như là một phần của một ứng dụng chức năng như vậy không có dấu ngoặc đơn là cần thiết.

Lưu ý rằng cùng tuyệt vời quy tắc ứng dụng chức năng gắn kết chặt chẽ hơn so với bất kỳ nhà điều hành ghi là những gì cho phép chúng ta viết length xs trong 1 + length xs mà không cần bất kỳ dấu ngoặc đơn. Quy tắc infix giveth và quy tắc infix bỏ đi.

+2

+1 cho các chữ cái cháy. Mã Haskell của tôi dừng lại trông giống như Lisp sau khi tôi tiếp thu quy tắc này. – Nefrubyr

+1

+1. Yêu câu cuối cùng –

14

Bạn chỉ cần sử dụng toán tử cons :, ưu tiên thấp. Dấu ngoặc đơn là cần thiết để mọi thứ ở bên phải.

Và bạn không sử dụng [x:xs], vì điều đó sẽ khớp với danh sách có phần tử duy nhất là danh sách có đầu x và đuôi xs.

+1

Tôi chưa từng thử mẫu '[x: xs]' cụ thể nào, nhưng tất nhiên là bạn đúng; nó khớp với một danh sách singleton ở cấp cao nhất. Ký hiệu desugared của pattern sẽ là: '((x: xs): [])'. –

3

Tôi không biết câu trả lời chính xác, nhưng tôi đoán đó là do những gì có thể được so khớp trong các mẫu. Chỉ các nhà xây dựng mới có thể được so khớp. Các nhà xây dựng có thể là từ đơn hoặc tổng hợp. Xem mã tiếp theo:

data Foo = Bar | Baz Int 

f :: Foo -> Int 
f Bar  = 1 
f (Baz x) = x - 1 

Từ đơn lẻ khớp với nhau. Nhưng các nhà xây dựng tổng hợp phải được bao quanh với các parens để tránh sự mơ hồ. Nếu chúng ta bỏ qua Parens có vẻ như phù hợp với hai lập luận độc lập:

f Baz x = x - 1 

Vì vậy, như (:) là composit nó phải nằm trong dấu ngoặc. Bỏ qua parens cho Bar là một loại đường cú pháp.

CẬP NHẬT: Tôi nhận ra rằng (như sykora đã lưu ý) đó là hậu quả của quyền ưu tiên của toán tử. Nó làm rõ các giả định của tôi. Ứng dụng chức năng (chỉ là không gian giữa hàm và đối số) có ưu tiên cao nhất. Những người khác bao gồm (:) có quyền ưu tiên thấp hơn. Vì vậy, f x:xs sẽ được hiểu là ((:) (f x)) xs có lẽ không phải là những gì chúng tôi cần. Trong khi f (x:xs) được hiểu là f được áp dụng cho x:xs, lần lượt là (:) được áp dụng cho xxs.

2

Đó là việc cần làm với phân tích cú pháp.

Hãy nhớ rằng, dấu hai chấm: chỉ là một hàm tạo được viết bằng cú pháp toán tử. Vì vậy, một chức năng như

foo [] = 0 
foo (x:xs) = x + foo xs 

cũng có thể được viết như

foo [] = 0 
foo ((:) x xs) = x + foo xs 

Nếu bạn thả ngoặc ở chỗ dòng cuối cùng, nó trở nên rất khó để phân tích!

1

: là một hàm tạo dữ liệu, giống như bất kỳ đối sánh mẫu nào khác, nhưng được in bằng văn bản. Các dấu ngoặc đơn hoàn toàn là do có ưu tiên infix; chúng thực sự không bắt buộc và có thể được bỏ qua một cách an toàn khi các quy tắc ưu tiên cho phép. Ví dụ:

> let (_, a:_) = (1, [2, 3, 4]) in a 
2 
> let a:_ = "xyzzy" 
'x' 
> case [1, 2, 3] of; a:b -> a; otherwise -> 0; 
1 

Điều thú vị là dường như không hoạt động trong đầu lambda. Không chắc chắn lý do tại sao. Như mọi khi, toán tử "juxtaposition" liên kết chặt chẽ hơn bất kỳ thứ gì khác, vì vậy thường không phải là dấu phân tách là cần thiết, nhưng chúng không thực sự là phần của kết hợp mẫu - nếu không bạn sẽ không thể sử dụng các mẫu như (x:y:zs) thay vì (x:(y:zs)).

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