x !! (-1)
hiện "an toàn hơn" điều và treo
Crashing không phải là an toàn. Thực hiện chức năng không hoàn toàn phá hủy khả năng của bạn để giải thích về hành vi của một hàm dựa trên loại của nó.
Chúng ta hãy tưởng tượng rằng take
và drop
đã có hành vi "bị lỗi trên âm".Hãy xem xét loại của họ:
take, drop :: Int -> [a] -> [a]
Một điều loại này chắc chắn không cho bạn biết rằng chức năng này có thể sụp đổ! Sẽ hữu ích nếu bạn sử dụng một ngôn ngữ tổng thể, mặc dù chúng tôi không - ý tưởng được gọi là fast and loose reasoning - nhưng để có thể thực hiện điều đó, bạn phải tránh sử dụng (và viết) các hàm không tổng nhiều nhất có thể.
Việc cần làm, sau đó, về các hoạt động có thể không thành công hoặc không có kết quả? Các loại là câu trả lời! Một thực sự an toàn biến thể của (!!)
sẽ có một loại mà mô hình các trường hợp thất bại, như:
safeIndex :: [a] -> Int -> Maybe a
Đây là một lợi thế cho các loại (!!)
,
(!!) :: [a] -> Int -> a
nào, bằng cách quan sát đơn giản, có thể không có (tổng số) cư dân - bạn không thể "phát minh" một a
nếu danh sách trống!
Cuối cùng, hãy quay lại take
và drop
. Mặc dù kiểu của họ không nói đầy đủ về hành vi, cùng với tên của họ (và lý tưởng là một vài thuộc tính QuickCheck), chúng tôi có một ý tưởng khá hay. Như những người phản ứng khác đã chỉ ra, hành vi này là thích hợp trong nhiều trường hợp. Nếu bạn thực sự là cần phải từ chối đầu vào độ dài phủ định, bạn không phải chọn giữa không tổng (bị rơi) hoặc khả năng hành vi đáng ngạc nhiên (chấp nhận độ dài phủ định) - mô hình kết quả có thể có trách nhiệm với các loại.
loại này làm cho nó rõ ràng rằng không có "kết quả" cho một số đầu vào:
takePos, dropPos :: Int -> [a] -> Maybe [a]
Vẫn còn tốt hơn, loại này sử dụng các số tự nhiên; Các hàm với loại này thậm chí không thể là được áp dụng cho số âm!
takeNat, dropNat :: Nat -> [a] -> [a]
Có những điều hợp lý và thường hữu ích cần làm khi đối số vượt quá giới hạn: "trả về toàn bộ danh sách gốc" hoặc "trả về danh sách trống". Bạn không thể xác định một cách hợp lý '(!! (-1))' ở tất cả, không có giá trị dự phòng để trả lại. –
Thực tế thú vị: ngữ nghĩa thay đổi giữa báo cáo Haskell 98 và 2010. [Ví dụ thực hiện] (https://www.haskell.org/onlinereport/list.html) trong 98 được sử dụng 'lỗi' nếu danh sách không trống và' n' là số âm, trong khi biến thể năm 2010 cho thấy giá trị âm có tác dụng tương tự như 'take 0'. – Zeta
@Zeta: đó là điều hấp dẫn, tuyệt vời! – Lynn