Dans quelles situations utiliser liftIO
? Lorsque j'utilise ErrorT String IO
, la fonction lift
fonctionne pour soulever IO actions dans ErrorT
, donc liftIO
semble superflu.
lift
se soulève toujours de la couche "précédente". Si vous devez vous soulever de la deuxième couche, vous aurez besoin de lift . lift
etc.
D'autre part, liftIO
se soulève toujours de la couche IO (qui, lorsqu'elle est présente, est toujours au bas de la pile). Donc, si vous avez plus de 2 couches de monades, vous apprécierez liftIO
.
Comparez le type de l'argument dans les lambdas suivantes:
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
liftIO est juste un raccourci vers la IO Monade, quelle que soit la Monade dans laquelle vous vous trouvez. Fondamentalement, liftIO équivaut à utiliser un nombre variable d'ascenseurs. Au début, cela peut sembler redondant, mais l'utilisation de liftIO a un grand avantage: cela rend votre code IO indépendant de la construction Monad réelle afin que vous puissiez réutiliser le même code quel que soit le nombre de couches de votre Monad final a été construit (c'est assez important lors de l'écriture d'un transformateur monade).
D'un autre côté, liftIO ne vient pas gratuitement, comme le fait ascenseur: les transformateurs Monad que vous utilisez doivent avoir un support pour cela, par exemple la Monade dans laquelle vous vous trouvez doit être une instance de la classe MonadIO, mais la plupart des Monades le font aujourd'hui (et bien sûr, le vérificateur de type vérifiera cela pour vous au moment de la compilation: c'est la force de Haskell!).