2012-04-04 23 views
5

Tôi nghĩ rằng tôi thiếu một số hiểu biết cơ bản của máy biến áp đơn nguyên, bởi vì tôi thấy mình viết code này:Lift giá trị lỗi để ErrorT đơn nguyên biến

import Control.Monad.Identity 
import Control.Monad.Error 

liftError :: Either String Int -> ErrorT String Identity Int 
liftError x = do case x of 
        Right val -> return val 
        Left err -> throwError err 

gateway :: Bool -> ErrorT String Identity Int 
gateway = liftError . inner 

inner :: Bool -> Either String Int 
inner True = return 5 
inner False = throwError "test" 

Trong khi làm việc này, tôi nghĩ rằng điều này có thể được thực hiện nhiều hơn thanh lịch. Đặc biệt, tôi đang tìm kiếm một sự thay thế của liftError, mà tôi nghĩ rằng tôi không cần phải xác định cho bản thân mình.

Cách đơn giản nhất để làm cho gatewayinner hoạt động cùng nhau mà không thay đổi loại của chúng là gì?

Trả lời

6

Nếu bạn chỉ thay đổi các loại một chút, bạn không phải làm gì cả.

{-# LANGUAGE FlexibleContexts #-} 

gateway :: Bool -> ErrorT String Identity Int 
gateway = inner 

inner :: MonadError String m => Bool -> m Int 
inner True = return 5 
inner False = throwError "test" 

MonadError có trường hợp cho cả ErrorTEither, vì vậy cách này bạn có thể sử dụng inner như cả hai.

+0

Được rồi, do đó, để cụ thể hơn, tôi phải viết chức năng nâng thủ công nếu tôi muốn để nguyên loại như vậy? Đây chỉ là sự hiểu biết của tôi. BTW tiếc là tôi không thể bỏ phiếu nữa hôm nay:/Bạn sẽ nhận được phiếu bầu vào ngày mai :) –

+1

Nếu không thay đổi các loại, bạn có thể sử dụng 'ErrorT. return' thay cho hàm 'liftError' của bạn. Bạn cũng có thể sử dụng phiên bản tổng quát hơn trong nội bộ và chỉ hiển thị bản sao của 'bên trong' với loại bị hạn chế. – hammar

+0

Đó là 'ErrorT. return' là chính xác những gì tôi đang tìm kiếm. Như tôi đã đề cập, điều này không liên quan gì đến bất kỳ mã thực nào, tôi chỉ muốn hiểu khái niệm về biến thế đơn nguyên :) –

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