2012-03-30 16 views
5

Tôi muốn biến biến đổi đơn nguyên của mình thành một thể hiện của MonadError nếu đơn vị được biến đổi là một cá thể. Về cơ bản tôi muốn biến tôi cư xử như các máy biến áp built-in làm, ví dụ có một ví dụ MonadError cho StateT:Tạo một biến thể đơn nguyên tùy chỉnh một thể hiện của MonadError

MonadError e m => MonadError e (StateT s m) 

Tôi đã cố gắng làm điều này:

instance MonadError e m => MonadError e (MyMonadT m) 

Nhưng GHC bắt đầu phàn nàn về undecidable trường hợp, rõ ràng là thư viện MTL chỉ cho phép các trường hợp không thể xác định, nhưng có cách nào để tránh điều đó không? Hoặc nó là OK trong trường hợp này và nó sẽ không gây ra bất kỳ vấn đề?

Trả lời

8

Điều này về cơ bản là tốt. UndecidableInstances không phải là tất cả những gì đáng sợ; tất cả điều đó có nghĩa là trình biên dịch có thể, thay vì tìm một thể hiện, đi vào một vòng lặp vô hạn. Điều đó âm thanh khá xấu, cho đến khi bạn nhận ra rằng GHC thực sự có một giới hạn về số bước cần thiết để tìm một thể hiện; sẽ không có gì sai nếu bạn không viết một trường hợp xấu, và các thông báo lỗi bạn nhận được thường sẽ làm cho nó rất rõ ràng những gì đã xảy ra sai. Chắc chắn nó ít đáng sợ hơn những thứ như OverlappingInstances (hoặc tệ hơn, IncoherentInstances).

Lý do khiếu nại là vì MonadError có phụ thuộc chức năng từ m đến e. Điều đó có nghĩa là sự lựa chọn của m xác định những gì e phải; tức là mỗi m chỉ được liên kết với một e. Việc kiểm tra điều này (Điều kiện Bảo hiểm) là bảo thủ, vì vậy thật dễ dàng để gặp phải các vấn đề như thế này, nơi bạn cố gắng và "recurse down a level" để chỉ định e.

Nó sẽ liệt kê tất cả các trường hợp mà nó xem xét để thử và tìm kiếm trường hợp tìm kiếm, vì vậy bạn sẽ thấy một loạt các dòng lặp lại. Nhưng thông thường bạn thậm chí sẽ không gặp rắc rối như thế này ngay từ đầu.

Các vấn đề liên quan