2013-08-21 24 views
6

Tôi không thể làm gì để mở rộng câu hỏi. Nhưng đây là một trường hợp sử dụng: giả sử bạn có hai máy biến áp đơn nguyên, ts, chuyển so với cùng đơn nguyên m:Có cách nào để tạo ra hai máy biến áp đơn nguyên nếu chúng thuộc loại khác nhau, nhưng đơn nguyên cơ bản của chúng là cùng loại?

master :: (MonadTrans t, Monad m) => t m a b 
slave :: (MonadTrans t, Monad m) => s m a b 

Và tôi muốn soạn masterslave như vậy mà họ có thể giao tiếp với nhau khi m nguyên thủy được nâng lên thành ts. Chữ ký có thể là:

bound :: (MonadTrans t, MonadTrans s, Monad m, Monoid a) => t m a b -> s m a b -> (...) 
But what is the type of (...) ? 

Một trường hợp sử dụng, trong ký hiệu có đường:

master :: Monoid a => a -> t m a b 
master a = do 
    a <- lift . send $ (a,False)  -- * here master is passing function param to slave 
    ...        -- * do some logic with a 
    b <- lift . send $ (mempty,True) -- * master terminates slave, and get back result 

slave :: Monoid a => (a -> b) -> s m a b 
slave g = do 
    (a,end) <- lift receive 
    case end of 
     True -> get >>= \b -> exit b 
     _ -> (modify (++[g a])) >> slave g 

Cập nhật: sendreceive là nguyên thủy của loại m.

Tôi xin lỗi nếu ví dụ này có vẻ giả tạo, hoặc giống như coroutines quá nhiều, tinh thần của câu hỏi thực sự không có gì để làm với nó vì vậy xin vui lòng bỏ qua tất cả tương đồng. Nhưng điểm chính là mono ts không thể được hợp lý sáng tác với nhau trước đây, nhưng sau khi cả hai bọc một số đơn nguyên cơ bản m, bây giờ chúng có thể được sáng tác và chạy như một hàm duy nhất. Đối với các loại chức năng sáng tác, tôi thực sự không chắc chắn vì vậy một số hướng được đánh giá cao. Bây giờ nếu trừu tượng này đã tồn tại và tôi chỉ không biết về nó, thì điều đó sẽ là tốt nhất.

+0

Là 's' và' t' tùy ý hoặc chúng bằng cách nào đó cụ thể - chúng ta đang cố gắng tạo ra 's' và' t'? Và câu hỏi tương tự cũng áp dụng cho 'm' - làm thế nào về nó và' send' và 'receive' của nó? –

+0

Có 's' và' t' là tùy ý. 'm' là kiểu cụ thể mà chúng ta đang cố tạo ở đây. 'send' và' receive' chỉ là các hàm nguyên thủy của kiểu '(a, Bool) -> m a b' và' m a b' tương ứng. Nhưng chúng là ngẫu nhiên đối với trường hợp sử dụng giả tạo mà tôi đưa ra, các chi tiết về việc triển khai chúng không quan trọng. – chibro2

Trả lời

8

Có. Kết hợp hoist từ gói mmorph với lift để làm điều này:

bound 
    :: (MonadTrans t, MonadTrans s, MFunctor t, Monad m) 
    => t m() -> s m() -> t (s m)() 
bound master slave = do 
    hoist lift master 
    lift slave 

Để hiểu tại sao các công trình này, nghiên cứu các loại hoist:

hoist :: (MFunctor t) => (forall x . m x -> n x) -> t m r -> t n r 

hoist phép bạn sửa đổi các đơn nguyên cơ sở của bất kỳ biến đơn nguyên mà thực hiện MFunctor (hầu hết trong số đó).

Mã nào cho bound là có hai máy biến áp đơn nguyên đồng ý về đơn nguyên mục tiêu cuối cùng, trong trường hợp này là t (s m). Thứ tự mà bạn làm tổ ts tùy thuộc vào bạn, vì vậy tôi chỉ giả định rằng bạn muốn t ở bên ngoài.

Sau đó, chỉ cần sử dụng các kết hợp khác nhau của hoistlift để nhận hai phép tính phụ để đồng ý về ngăn xếp đơn lẻ cuối cùng. Người đầu tiên làm việc như thế này:

master :: t m r 
hoist lift master :: t (s m) r 

Điều thứ hai làm việc như thế này:

slave :: s m r 
lift slave :: t (s m) r 

Bây giờ cả hai đều đồng ý vì vậy chúng tôi có thể trình tự chúng trong cùng một do khối và nó sẽ "chỉ làm việc".

Để tìm hiểu thêm về cách hoạt động của hoist, tôi khuyên bạn nên kiểm tra the documentation cho gói mmorph có số a nice tutorial ở dưới cùng.

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