Hầu hết mọi người tránh đưa ra các mô tả chính xác về phạm trù cú pháp là gì, bởi vì nếu bạn thực hiện đúng với tất cả các chi tiết, tỷ lệ hiểu biết sâu sắc đối với sự tinh vi toán học cần thiết sẽ kết thúc rất, rất thấp. Cuốn sách Lý thuyết về ngôn ngữ lập trình của John Reynold có một trong những giải thích toàn diện hơn trong chương 1, cũng như Cơ sở thực tiễn về ngôn ngữ lập trình của Robert Harper .
Trực giác bạn nên có là một thể loại cú pháp là tập hợp các cây được tạo bởi một ngữ pháp tự do ngữ cảnh. Đưa ra định nghĩa như vậy cho một tập hợp các cây, bạn có thể định nghĩa các hàm trên tập hợp này bằng cách sử dụng đệ quy cấu trúc và chứng minh các thuộc tính về chúng bằng cách sử dụng cảm ứng cấu trúc : tức là bằng cách phân tích trường hợp tất cả các cách khác nhau mà cây có thể được xây dựng.
Ví dụ: giả sử rằng chúng ta có ngôn ngữ của các phép toán số học được đưa ra bởi ngữ pháp sau:
e ::= zero | succ(e)| add(e, e)
Sau đó, chúng ta có thể định nghĩa một hàm diễn giải eval
có một thuật ngữ và cung cấp cho bạn một số nguyên, theo các trường hợp về cách chúng ta có thể xây dựng một thuật ngữ:
eval : Expr -> Int
eval zero = 0
eval succ(e) = 1 + eval e
eval add(e, e') = eval e + eval e'*
Lưu ý rằng chúng ta đã hoàn toàn xác định hàm này bằng cách đưa ra một mệnh đề cho mỗi cách có thể, chúng ta có thể tạo ra một biểu thức từ ngữ pháp. Thực tế rằng đây là một định nghĩa đầy đủ của một chức năng được gọi là nguyên tắc đệ quy cấu trúc .
Chúng ta cũng có thể chứng minh các thuộc tính về chức năng này bằng cách sử dụng cảm ứng cấu trúc - bằng cách thực hiện phân tích quy nạp cho từng trường hợp. Ví dụ, chúng ta có thể chứng minh rằng cho mọi e
, eval e ≥ 0
.
Proof. By structural induction on e.
- Case e = zero:
By the definition of eval, eval zero = 0.
We know 0 ≥ 0 by reflexivity of ≥.
- Case e = succ(e'):
By induction, we know that eval e' ≥ 0
So we also know that 1 + eval e' ≥ eval e'.
By transitivity, 1 + eval e' ≥ 0.
But eval succ(e') = 1 + eval e'.
So eval succ(e') ≥ 0.
- Case e = add(e', e'').
By induction, we know that eval e' ≥ 0.
By induction, we know that eval e'' ≥ 0.
By properties of addition, we know that eval e' + eval e'' ≥ 0.
By the definition of eval, eval add(e',e'') = eval e' + eval e''.
So eval add(e',e'') ≥ 0.
Thực tế là chỉ xem xét các trường hợp về cách thức biểu thức có thể tạo thành một bằng chứng được gọi là nguyên tắc cảm ứng cấu trúc .
Bây giờ, thực tế là người ta có thể định nghĩa các hàm bằng đệ quy cấu trúc và chứng minh các thuộc tính bằng cảm ứng cấu trúc cho bất kỳ ngữ pháp nào . Tuy nhiên, việc chứng minh điều này một cách khắt khe đòi hỏi một lượng lý thuyết thể loại nhất định; bạn cần chính thức hóa các thể loại cú pháp như các đại số ban đầu của một lớp functor nhất định, và sau đó chứng minh rằng các đại số ban đầu như vậy luôn tồn tại cho lớp đó.
Đây thực sự là công cụ nặng nề để chứng minh một kết quả "rõ ràng" như vậy, và vì vậy tôi khuyên bạn chỉ nên tin vào trực giác của bạn về cách định nghĩa cấu trúc hoạt động, và sau đó chỉ bận tâm với ngữ nghĩa chi tiết của chúng nếu bạn quyết định trở thành một nhà logic học chuyên nghiệp.