Vấn đề
Hãy xem xét các vấn đề thiết kế sau đây trong Haskell. Tôi có một EDSL đơn giản, tượng trưng trong đó tôi muốn biểu thị các biến và biểu thức tổng quát (đa thức đa biến) như x^2 * y + 2*z + 1
. Ngoài ra, tôi muốn diễn đạt các phương trình biểu tượng nhất định trên các biểu thức, nói x^2 + 1 = 1
, cũng như các định nghĩa , như thế nào x := 2*y - 2
.
Mục tiêu là để:
- Có một loại riêng cho các biến và biểu thức chung - một số hàm nhất định có thể được áp dụng cho các biến và không phải là biểu thức phức tạp. Ví dụ, một định nghĩa toán tử
:=
có thể là kiểu(:=) :: Variable -> Expression -> Definition
và nó không phải là có thể vượt qua một biểu thức phức tạp như thông số bên trái tay của mình (mặc dù nó nên có thể để vượt qua một biến như tham số bên tay phải của mình, mà không cần đúc rõ ràng ) . - Có các biểu thức là một ví dụ
Num
, để có thể quảng bá các số nguyên cho các biểu thức và sử dụng một ký hiệu thuận tiện cho các hoạt động đại số thông thường như cộng hoặc nhân mà không cần đưa ra một số toán tử trình bao bọc phụ trợ.
Nói cách khác, tôi muốn có một kiểu truyền ẩn và tĩnh (ép buộc) các biến thành biểu thức. Bây giờ, tôi biết rằng như vậy, không có phôi kiểu ẩn trong Haskell. Tuy nhiên, một số khái niệm lập trình hướng đối tượng nhất định (kế thừa đơn giản, trong trường hợp này) có thể biểu thị được trong hệ thống loại của Haskell, có hoặc không có phần mở rộng ngôn ngữ. Làm thế nào tôi có thể đáp ứng cả hai điểm trên trong khi vẫn giữ một cú pháp nhẹ? Nó thậm chí có thể?
Thảo luận
Rõ ràng vấn đề chính ở đây là Num
hạn chế loại, vd
(+) :: Num a => a -> a -> a
Về nguyên tắc, có thể viết một kiểu dữ liệu đại số (tổng quát) cho cả hai biến và biểu thức. Sau đó, người ta có thể viết :=
theo cách như vậy, biểu thức phía bên trái bị phân biệt đối xử và chỉ có một hàm tạo biến được chấp nhận, với lỗi thời gian chạy khác. Tuy nhiên, đó không phải là một giải pháp sạch, tĩnh (tức là thời gian biên dịch) ...
Thí dụ
Lý tưởng nhất, tôi muốn đạt được một cú pháp nhẹ như
computation = do
x <- variable
t <- variable
t |:=| x^2 - 1
solve (t |==| 0)
Cụ thể, tôi muốn cấm ký hiệu như
t + 1 |:=| x^2 - 1
từ đó :=
nên đưa ra định nghĩa về một biến và không phải là toàn bộ biểu thức phía bên trái.
FromVar
typeclass sẽ được giúp đỡ. Tôi muốn tránh các diễn viên rõ ràng trong khi giữ Expr
một ví dụ Num
. Tôi đã chỉnh sửa câu hỏi thêm một ví dụ về ký hiệu mà tôi muốn đạt được.
class FromVar e
phương thứcfromVar :: Variable -> e
và cung cấp các thể hiện choExpression
vàVariable
sau đó các biến của bạn có các kiểu đa hình,x :: FromVar e => e
v.v. Tôi chưa kiểm tra xem nó hoạt động tốt như thế nào kể từ khi tôi sử dụng điện thoại của mình.