负位置的 IO 动作会产生意想不到的结果吗?
Can IO action in negative position give unexpected results?
关于 Monad IO
和 IO
之间的区别,似乎有一些未记录的知识。备注 here and here) 暗示 IO a
可以用在负数位置,但可能会产生意想不到的后果:
引用 Snoyman 1:
However, we know that some control flows (such as exception handling)
are not being used, since they are not compatible with MonadIO.
(Reason: MonadIO requires that the IO be in positive, not negative,
position.) This lets us know, for example, that foo is safe to use in
a continuation-based monad like ContT or Conduit.
和克密特 2:
I tend to export functions with a MonadIO constraint... whenever it
doesn't have to take an IO-like action in negative position (as an
argument).
When my code does have to take another monadic action as an argument,
then I usually have to stop and think about it.
程序员应该了解的此类功能是否存在危险?
例如,这是否意味着 运行 任意基于延续的操作可能会重新定义控制流,以基于 Monad IO
的接口安全的方式产生意想不到的结果?
Is there danger in such functions that programmers should know about?
没有危险。恰恰相反,Snoyman 和 Kmett 提出的观点是,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
.
关于 Monad IO
和 IO
之间的区别,似乎有一些未记录的知识。备注 here and here) 暗示 IO a
可以用在负数位置,但可能会产生意想不到的后果:
引用 Snoyman 1:
However, we know that some control flows (such as exception handling) are not being used, since they are not compatible with MonadIO. (Reason: MonadIO requires that the IO be in positive, not negative, position.) This lets us know, for example, that foo is safe to use in a continuation-based monad like ContT or Conduit.
和克密特 2:
I tend to export functions with a MonadIO constraint... whenever it doesn't have to take an IO-like action in negative position (as an argument).
When my code does have to take another monadic action as an argument, then I usually have to stop and think about it.
程序员应该了解的此类功能是否存在危险?
例如,这是否意味着 运行 任意基于延续的操作可能会重新定义控制流,以基于 Monad IO
的接口安全的方式产生意想不到的结果?
Is there danger in such functions that programmers should know about?
没有危险。恰恰相反,Snoyman 和 Kmett 提出的观点是,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
.