2010-10-13 27 views
64

Trong trường hợp nào nên sử dụng liftIO? Khi tôi đang sử dụng ErrorT String IO, chức năng lift hoạt động để nâng các tác vụ IO vào ErrorT, vì vậy liftIO có vẻ không cần thiết.Haskell: lift vs liftIO

Trả lời

75

lift luôn nâng lên từ lớp "trước đó". Nếu bạn cần phải nâng từ lớp thứ hai, bạn sẽ cần lift . lift và cứ thế.

Mặt khác, liftIO luôn luôn nâng từ lớp IO (trong đó, khi có mặt, luôn ở dưới cùng của ngăn xếp). Vì vậy, nếu bạn có nhiều hơn 2 lớp monads, bạn sẽ đánh giá cao liftIO.

Hãy so sánh các loại lập luận trong lambdas sau:.

type T = ReaderT Int (WriterT String IO) Bool 

> :t \x -> (lift x :: T) 
\x -> (lift x :: T) :: WriterT String IO Bool -> T 

> :t \x -> (liftIO x :: T) 
\x -> (liftIO x :: T) :: IO Bool -> T 
+26

Tôi thường sẽ sử dụng 'liftIO' để nâng lên lớp IO ngay cả khi' lift' là đủ, vì sau đó tôi có thể thay đổi ngăn xếp đơn và mã vẫn hoạt động. –

+11

@ John: điểm tốt. Và nó cũng làm cho nó rõ ràng rằng bạn đang nâng IO và không phải bất kỳ đơn nguyên khác. –

28

liftIO chỉ là một phím tắt để IO đơn nguyên, tùy theo các đơn nguyên bạn đang ở trong Về cơ bản, liftIO bằng việc sử dụng một số biến của thang máy . Lúc đầu điều này nghe có vẻ dư thừa nhưng việc sử dụng liftIO có một lợi thế lớn: nó làm cho mã IO của bạn trở nên độc lập với cấu trúc Monad thực tế để bạn có thể tái sử dụng cùng một mã bất kể số lượng lớp Monad cuối cùng của bạn đã được xây dựng (điều này khá quan trọng khi viết một biến áp đơn nguyên).

Trên bàn tay ồ ạt, liftIO không đến miễn phí, như thang máy: máy biến áp Monad bạn đang sử dụng phải có hỗ trợ cho nó, ví dụ: Monad bạn đang ở phải là một thể hiện của lớp MonadIO, nhưng hầu hết Monads ngày nay làm (và tất nhiên, trình kiểm tra kiểu sẽ kiểm tra điều này cho bạn tại thời gian biên dịch: đó là sức mạnh của Haskell!).

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