Bạn có thể sử dụng một kiểu dữ liệu trừu tượng với một smart constructor:
newtype Digit = Digit { digitVal :: Int }
deriving (Eq, Ord, Show)
mkDigit :: Int -> Maybe Digit
mkDigit n
| n >= 0 && n < 10 = Just (Digit n)
| otherwise = Nothing
Nếu bạn đặt điều này trong mô-đun khác và không xuất khẩu các nhà xây dựng Digit
, sau đó mã khách hàng không thể xây dựng giá trị của loại Digit
nằm ngoài phạm vi [0,9], nhưng bạn phải tự quấn và mở nó ra để sử dụng nó. Bạn có thể định nghĩa một cá thể Num
thực hiện phép tính số học, nếu điều đó có ích; điều đó cũng sẽ cho phép bạn sử dụng các chữ số để xây dựng các chữ số. (Tương tự như vậy cho Enum
và Bounded
.)
Tuy nhiên, điều này không đảm bảo rằng bạn không bao giờ thử để tạo ra một chữ số không hợp lệ, chỉ là bạn không bao giờ làm. Nếu bạn muốn đảm bảo hơn, thì giải pháp thủ công Jan cung cấp tốt hơn, với chi phí ít thuận tiện hơn. (Và nếu bạn định nghĩa một cá thể Num
cho loại chữ số đó, nó sẽ kết thúc bằng "không an toàn", bởi vì bạn có thể viết 42 :: Digit
nhờ hỗ trợ chữ số bạn muốn.)
(Nếu bạn không biết newtype
là gì, đó là về cơ bản data
cho dữ liệu loại với một lĩnh vực nghiêm ngặt duy nhất;. một wrapper Newtype xung quanh T sẽ có đại diện thời gian chạy giống như T đó là về cơ bản chỉ là một tối ưu hóa, vì vậy bạn có thể giả vờ nó nói data
với mục đích hiểu điều này.)
Chỉnh sửa: Đối với giải pháp 100% theo định hướng lý thuyết hơn, hãy xem phần nhận xét khá chật chội của câu trả lời này.
Điều đó sẽ thực hiện công việc, nhưng hệ thống kiểu không phải là điều đang xử lý sự cố. Đó là những gì tôi đang làm. –
Quyền - đảm bảo bổ sung ở đây là không có giá trị nào của loại 'Chữ số' có thể không hợp lệ, trái ngược với việc chỉ xác thực một' Expr' sau sự kiện. Lưu ý rằng ngay cả giải pháp liệt kê thủ công cũng cho phép các giá trị như 'lỗi 'oops" :: Chữ số'. Có nhiều cách để xử lý những điều này một cách mạnh mẽ và thuận tiện trong các hệ thống kiểu tiên tiến, nhưng chúng chưa thực hiện theo cách của họ vào Haskell, vì vậy một sự thỏa hiệp như thế này có thể là giải pháp tốt nhất. (Không phải là họ đã làm cho nó thành bất kỳ ngôn ngữ "thế giới thực" nào khác.) – ehird
Nếu hệ thống kiểu đang xử lý vấn đề, tôi sẽ không phải xác thực 'Expr' vì nó sẽ không biên dịch trong nơi đầu tiên, phải không? –