Tôi đang theo dõi "giấy Kleisli mũi tên của tài sản thái quá" Conor McBride và tôi đã đăng triển khai mã của mình here. Tóm lại, ông định nghĩa các loại và các lớp học sau:Rebinding ký hiệu cho monads được lập chỉ mục
type a :-> b = forall i . a i -> b i
class IFunctor f where imap :: (a :-> b) -> (f a :-> f b)
class (IFunctor m) => IMonad m where
skip :: a :-> m a
bind :: (a :-> m b) -> (m a :-> m b)
data (a := i) j where
V :: a -> (a := i) i
Sau đó, ông định nghĩa hai loại với phím tắt, thì sau đó sử dụng (:=)
để hạn chế chỉ số ban đầu:
-- Conor McBride's "demonic bind"
(?>=) :: (IMonad m) => m a i -> (a :-> m b) -> m b i
(?>=) = flip bind
-- Conor McBride's "angelic bind"
(>>=) :: (IMonad m) => m (a := j) i -> (a -> m b j) -> m b i
m >>= f = bind (\(V a) -> f a) m
Các ràng buộc thứ hai làm việc hoàn toàn tốt đẹp để rebinding do
ký hiệu để sử dụng các đơn vị được lập chỉ mục có đuôi mở rộng RebindableSyntax
, sử dụng các định nghĩa tương ứng sau cho return
và fail
:
return :: (IMonad m) => a -> m (a := i) i
return = skip . V
fail :: String -> m a i
fail = error
... nhưng vấn đề là tôi không thể nhận được ràng buộc trước đây (tức là (?>=)
) để hoạt động. Tôi đã cố gắng thay vì xác định (>>=)
và return
là:
(>>=) :: (IMonad m) => m a i -> (a :-> m b) -> m b i
(>>=) = (?>=)
return :: (IMonad m) => a :-> m a
return = skip
Sau đó, tôi đã tạo ra một kiểu dữ liệu được bảo đảm để sống một chỉ số cụ thể:
data Unit a where
Unit :: Unit()
Nhưng khi tôi cố gắng kết nối lại các do
ký hiệu sử dụng các định nghĩa mới cho (>>=)
và return
, nó không hoạt động, như được minh họa trong ví dụ sau:
-- Without do notation
test1 = skip Unit >>= \Unit -> skip Unit
-- With do notation
test2 = do
Unit <- skip Unit
skip Unit
test1
type-séc, nhưng test2
không, đó là lạ, vì tôi nghĩ rằng tất cả những gì RebindableSyntax
đã được phép do
ký hiệu desugar test2
-test1
, vì vậy nếu test1
type-séc, thì tại sao không làm test2
? Các lỗi tôi nhận được là:
Couldn't match expected type `t0 -> t1'
with actual type `a0 :-> m0 b0'
Expected type: m0 a0 i0 -> (t0 -> t1) -> m Unit()
Actual type: m0 a0 i0 -> (a0 :-> m0 b0) -> m0 b0 i0
In a stmt of a 'do' block: Unit <- skip Unit
In the expression:
do { Unit <- skip Unit;
skip Unit }
lỗi vẫn còn ngay cả khi tôi sử dụng forall
cú pháp rõ ràng thay vì các nhà điều hành :->
loại.
Bây giờ, tôi biết có một vấn đề khác khi sử dụng "liên kết ma quỷ", đó là bạn không thể xác định (>>)
, nhưng tôi vẫn muốn xem tôi có thể đi xa đến mức nào. Ai có thể giải thích tại sao tôi không thể nhận được GHC để desugar "ràng buộc ma quỷ", ngay cả khi nó bình thường gõ-kiểm tra?
Vì điều này xuất hiện trong [câu hỏi trùng lặp mới hơn] (http://stackoverflow.com/questions/33488322/ranknpolymorphism-and-kleisli-arrows-of-outrageous-fortune), tôi sẽ chỉ ra rằng ngày nay GHC (hiện tại 7.10.2) hầu như không hỗ trợ 'ImpredicativeTypes' chút nào, do đó, nhiều hơn ký hiệu' do' ngắt cho mã này ngay bây giờ. –