Есть ли опасность в таких функциях, о которых должны знать программисты?
Нет опасности.Скорее наоборот, смысл, который делают Снойман и Кметт, состоит в том, что Monad IO
не позволяет вам поднимать вещи с IO
в отрицательном позитиве.
Предположим, вы хотите обобщить putStrLn :: String -> IO ()
.Вы можете, потому что IO
находится в положительной позиции:
putStrLn' :: MonadIO m => String -> m ()
putStrLn' str = liftIO (putStrLn str)
Теперь предположим, что вы хотите обобщить handle :: Exception e => (e -> IO a) -> IO a -> IO a
.Вы не можете (по крайней мере, только с MonadIO
):
handle' :: (MonadIO m, Exception e) => (e -> m a) -> m a -> m a
handle' handler act = liftIO (handle (handler . unliftIO) (unliftIO act))
unliftIO :: MonadIO m => m a -> IO a
unliftIO = error "MonadIO isn't powerful enough to make this implementable!"
Вам нужно что-то еще.Если вам интересно, как вы это сделаете, взгляните на реализацию функций в lifted-base
.Например: handle :: (MonadBaseControl IO m, Exception e) => (e -> m a) -> m a -> m a
.