2012-06-14 31 views
21

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 returnfail:

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 (>>=)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 (>>=)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?

+0

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ờ. –

Trả lời

9

IIUC, trình gỡ lỗi GHC thực sự chạy sau máy đánh chữ (source). Điều đó giải thích lý do tại sao tình huống bạn quan sát về mặt lý thuyết là có thể. Người đánh máy có thể có một số quy tắc nhập đặc biệt cho ký hiệu, và những người này có thể không phù hợp với những gì người đánh máy sẽ làm với mã desugarred.

Tất nhiên, thật hợp lý để mong đợi chúng nhất quán, vì vậy tôi khuyên bạn nên đệ trình lỗi GHC.

+2

Cảm ơn bạn đã liên kết. Tôi sẽ kiểm tra điều này. Nếu họ đồng ý đó là lý do cho loại lỗi, tôi sẽ chấp nhận câu trả lời của bạn. –

+2

Tôi cũng muốn biết điều gì đang xảy ra. Tôi phải đối mặt với cùng một vấn đề, nhưng ít bị kích động. Tôi hy vọng sự đa hình ma quỷ là bất ngờ: nó rất ngạc nhiên của mọi người. – pigworker

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