Đây là tiện ích mở rộng Scoped Type Variables GHC tại nơi làm việc. Theo liên kết để tìm hiểu thêm.
Về cơ bản, bạn xác định xác nhận về loại phải được patter đáp ứng trước khi nó có thể khớp. Vì vậy, yeah, nó giống như bảo vệ, nhưng không hoàn toàn như vậy.
Ví dụ cụ thể này hoạt động như thế nào? Lặn vào sources of "base" library để tìm ra rằng:
class (Show e) => Exception e where
toException :: e -> SomeException
fromException :: SomeException -> Maybe e
data SomeException = forall e . Exception e => SomeException e
instance Exception IOException where
toException = IOException
fromException (IOException e) = Just e
fromException _ = Nothing
instance Exception ArithException where
toException = ArithException
fromException (ArithException e) = Just e
fromException _ = Nothing
Chúng ta thấy rằng IOException
và ArithException
nhiều loại khác nhau thực hiện typeclass Exception
. Chúng tôi cũng thấy rằng toException/fromException
là một gói/unwrapping cơ chế cho phép một để chuyển đổi giá trị của loại Exception
đến/từ các giá trị của các loại IOException
, ArithException
vv
Vì vậy, chúng ta có thể đã viết:
f = expr `catches` [Handler handleArith,
Handler handleIO]
handleArith :: ArithException -> IO()
handleArith ex = ....
handleIO :: IOException -> IO()
handleIO ex = ....
Giả sử rằng IOException
xảy ra. Khi catchesHandler
xử lý phần tử đầu tiên của danh sách trình xử lý, nó gọi tryHandler
, gọi số fromException
. Từ định nghĩa của tryHandler
nó tuân theo kiểu trả về của fromException
phải giống như đối số của handleArith
. Mặt khác, e
là loại Ngoại lệ, cụ thể là - (IOException ...). Vì vậy, các loại diễn ra theo cách này (đây không phải là một Haskell hợp lệ, nhưng tôi hy vọng rằng bạn sẽ có được quan điểm của tôi):
fromException :: (IOException ...) -> Maybe ArithException
Từ instance Exception IOException ...
nó sau ngay lập tức mà kết quả là Nothing
, vì vậy xử lý này được bỏ qua . Bởi cùng một lý do, trình xử lý sau sẽ được gọi, bởi vì fromException
sẽ trả về (Just (IOException ...))
.
Vì vậy, bạn đã sử dụng chữ ký loại handleArith
và handleIO
để chỉ định khi nào mỗi người trong số họ sẽ được gọi và fromException/toException
đảm bảo rằng nó đã xảy ra theo cách này.
Nếu muốn, bạn cũng có thể hạn chế các loại handleIO
và handleArith
bên trong định nghĩa f
, sử dụng các biến kiểu phạm vi. Có thể cho rằng, điều này có thể giúp bạn dễ đọc hơn.
Hoàn tất, Biến loại phạm vi không phải là người chơi chính ở đây. Chúng chỉ được sử dụng để thuận tiện. Máy móc chính để chơi loại thủ thuật này là fromException/toException
và bạn bè. Biến kiểu Scoped chỉ cho phép bạn có cú pháp gần giống với các mẫu bảo vệ.
Biến kiểu phạm vi có liên quan như thế nào? Tôi không thấy cơ chế này tại nơi làm việc trong nguồn bắt. – me2
Được cập nhật để giải thích từ thủ thuật ngoại lệ/ngoại lệ – ADEpt