84

どのような状況liftIOで使用する必要がありますか? を使用している場合ErrorT String IOlift関数は IO アクションを に持ち上げるために機能するErrorTため、liftIO余分なようです。

4

3 に答える 3

96

lift常に「前の」レイヤーから持ち上げます。2 番目のレイヤーから持ち上げる必要がある場合は、必要になりますlift . lift

一方、liftIO常に IO レイヤー (存在する場合、常にスタックの一番下にあります) から持ち上げます。したがって、2 層以上のモナドがある場合は、liftIO.

次のラムダで引数の型を比較します。

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
于 2010-10-13T06:32:06.863 に答える
39

liftIO は、IO モナドへのショートカットにすぎません。基本的に、liftIO は可変数のリフトを使用することと同じです。最初はこれは冗長に聞こえるかもしれませんが、liftIO を使用することには 1 つの大きな利点があります: IO コードが実際の Monad 構築から独立しているため、最終的な Monad が構築されたレイヤーの数に関係なく、同じコードを再利用できます (これは非常に重要です)。モナド変換子を書くとき)。

一方、lift がそうであるように、liftIO は無料で提供されているわけではありません。使用している Monad トランスフォーマーはそれをサポートしている必要があります。たとえば、使用している Monad は MonadIO クラスのインスタンスである必要がありますが、最近のほとんどの Monad はサポートしています。 (もちろん、型チェッカーはコンパイル時にこれをチェックします。これが Haskell の強みです!)。

于 2010-10-13T13:06:13.810 に答える