tôi đã xác định một cấu trúc cây biểu hiện trong F # như sau:trận đấu Incomplete với VÀ mẫu
type Num = int
type Name = string
type Expr =
| Con of Num
| Var of Name
| Add of Expr * Expr
| Sub of Expr * Expr
| Mult of Expr * Expr
| Div of Expr * Expr
| Pow of Expr * Expr
| Neg of Expr
tôi muốn để có thể khá-in cây biểu hiện vì vậy tôi đã làm như sau:
let (|Unary|Binary|Terminal|) expr =
match expr with
| Add(x, y) -> Binary(x, y)
| Sub(x, y) -> Binary(x, y)
| Mult(x, y) -> Binary(x, y)
| Div(x, y) -> Binary(x, y)
| Pow(x, y) -> Binary(x, y)
| Neg(x) -> Unary(x)
| Con(x) -> Terminal(box x)
| Var(x) -> Terminal(box x)
let operator expr =
match expr with
| Add(_) -> "+"
| Sub(_) | Neg(_) -> "-"
| Mult(_) -> "*"
| Div(_) -> "/"
| Pow(_) -> "**"
| _ -> failwith "There is no operator for the given expression."
let rec format expr =
match expr with
| Unary(x) -> sprintf "%s(%s)" (operator expr) (format x)
| Binary(x, y) -> sprintf "(%s %s %s)" (format x) (operator expr) (format y)
| Terminal(x) -> string x
Tuy nhiên, tôi không thực sự thích cách tiếp cận failwith
cho hàm operator
vì nó không an toàn trong thời gian biên dịch. Vì vậy, tôi viết lại nó như là một mô hình hoạt động:
let (|Operator|_|) expr =
match expr with
| Add(_) -> Some "+"
| Sub(_) | Neg(_) -> Some "-"
| Mult(_) -> Some "*"
| Div(_) -> Some "/"
| Pow(_) -> Some "**"
| _ -> None
Bây giờ tôi có thể viết lại chức năng format
của tôi đẹp như sau:
let rec format expr =
match expr with
| Unary(x) & Operator(op) -> sprintf "%s(%s)" op (format x)
| Binary(x, y) & Operator(op) -> sprintf "(%s %s %s)" (format x) op (format y)
| Terminal(x) -> string x
tôi cho rằng, kể từ khi F # là ma thuật, mà điều này chỉ có thể làm việc. Thật không may, trình biên dịch cảnh báo tôi về các kết quả mẫu không hoàn chỉnh, vì không thể thấy bất kỳ thứ gì khớp với Unary(x)
cũng sẽ khớp với Operator(op)
và bất kỳ thứ gì khớp với Binary(x, y)
cũng sẽ khớp với Operator(op)
. Và tôi xem xét các cảnh báo như vậy là xấu như lỗi trình biên dịch. Vì vậy, câu hỏi của tôi là: Có một lý do cụ thể tại sao điều này không hoạt động (như tôi đã để lại một số chú giải phép thuật ở đâu đó hoặc có điều gì đó mà tôi không thấy)? Có cách giải quyết đơn giản nào tôi có thể sử dụng để có được loại an toàn tôi muốn không? Và có một vấn đề cố hữu với kiểu kiểm tra biên dịch thời gian này hay là một thứ gì đó mà F # có thể thêm vào trong một số bản phát hành trong tương lai?
Tôi nghĩ rằng loại vấn đề này không thể sửa được. Trong trường hợp chung, nó sẽ yêu cầu giải quyết vấn đề dừng. Tôi nghĩ rằng giải pháp thanh lịch nhất sẽ là thêm một lớp thêm các mẫu để bạn trả về 'Unary (x, op)'. –
Tôi thực sự xem xét việc đó, nhưng tôi muốn giữ mô hình của mình cụ thể cho một trường hợp sử dụng (phân loại tính xác thực của biểu thức và trích xuất các đối số của nó). – luksan