2012-03-14 18 views
7

Tôi có một đơn nguyên cho một tính toán rằng có thể thất bại và làm một số đăng nhập:Đang cập nhật đơn nguyên bên ngoài chỉ trong biến đơn nguyên

f1 :: WriterT [String] (Either String) a 

Tôi có một chức năng mà sẽ không thất bại nhưng hiện một số logging:

f2 :: Writer [String] b 

Cách tốt nhất để cập nhật đơn vị ghi trong f1 bằng cách sử dụng nhật ký từ f2 và nắm bắt đầu ra của tính toán f2? Tại thời điểm này tôi đang thực hiện điều này:

f2result <- (\(r,l) -> do {tell l; return r}) (runWriter f2) 

Tôi đang sử dụng thang máy để cập nhật đơn vị bên trong với tính toán khác, vì vậy hãy chuyển đổi xung quanh Writer và Monome sẽ không giải quyết được sự cố.

+0

Cảm ơn danr và rampion cho câu trả lời của bạn. Tôi đã chọn sử dụng phương thức bọc. Mặc dù tôi có thể thay đổi kiểu f2, hàm đó xuất hiện trong các ngữ cảnh khác, do đó tôi muốn viết kiểu của nó mà không tham chiếu đến các nhu cầu của một hàm gọi cụ thể. – mskel

Trả lời

4

Nếu bạn định nghĩa f2, cách tiếp cận đơn giản nhất lý có thể là cấu trúc lại f2 vì vậy nó được định nghĩa thusly:

f2 :: Monad m => WriterT [String] m b 

nào không nên quá khắt khe, vì Writer w b được định nghĩa là WriterT w Identity b, và Identity đơn nguyên doesn không cung cấp cho bạn bất cứ điều gì.

Sau đó, bạn có thể chuỗi chúng chỉ bằng cách thực hiện f1 >> f2.

Nếu bạn không thể xác định lại f2, bạn luôn có thể định nghĩa của riêng bạn với các chữ ký phù hợp:

f2' :: Monad m => WriterT [String] m b 
f2' = WriterT . return $ runWriter f2 

Và nếu bạn đã là một loạt các f2 để quấn, bạn luôn có thể định nghĩa một chức năng để quấn chúng cho bạn

wrap :: Monad m => Writer w b -> WriterT w m b 
wrap = WriterT . return . runWriter 

vì vậy, bạn có thể làm f1 >> wrap f2a >> wrap f2b >> wrap f2c ...

4

là một theo dõi về câu trả lời rampion, bạn có thể thay ref diễn viên f2 trên bất kỳ MonadWriter:

f2 :: MonadWriter [String] m => m a 

nên trong không thể thay đổi định nghĩa của nó bạn có thể quấn nó tương tự như rampion làm:

f2' :: MonadWriter [String] m => m a 
f2' = do let (a,w) = runWriter f2 
     tell w 
     return a 

Các [String] lập luận để MonadWriter đòi hỏi pragma GHC này:

{-# LANGUAGE FlexibleContexts #-} 

Như mọi khi, pragmas ar e đặt trên đỉnh của mô-đun.

Trong những ý kiến, rampion đã đưa ra một phiên bản của gói một chức năng trong cài đặt này:

wrap :: MonadWriter w m => Writer w b -> m b 
wrap = uncurry (<<) . (return *** tell) . runWriter 
    where (<<) = flip (>>) 
+1

và trình bao bọc trở thành 'wrap :: MonadWriter w m => Writer w b -> m b; wrap = uncurry (<<). (trở lại *** nói). runWriter ở đâu (<<) = flip (>>) ' – rampion

+0

@ rampion: Tuyệt vời!Tôi có thể đánh giá cao phong cách pointfree;) – danr

+0

Vâng, hãy để tôi tham gia vào xã hội ngưỡng mộ lẫn nhau, và nói rằng tôi có thể đánh giá cao việc khái quát hóa cho MonecWriter typeclass :) – rampion

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