它是否会破坏组合以修改Haskell中的输入?

Car*_*ong 0 monads haskell sdl functional-programming purely-functional

当我阅读SDLhaskell 的文档时,我发现一些函数不可避免地修改了它的输入.例如,blitSurface将目标曲面作为输入,但在函数内更新.现在,概括问题,如果我有一个函数f :: a -> IO a,如果我a在函数内修改它会破坏组合吗?怎么样f :: IO a -> IO a?怎么样a -> IO ()?那怎么样IO a -> IO ()

考虑到blitSurface实际上是外来函数的情况,并且每帧的新表面听起来效率不高,这些函数很难避免.这些功能会导致更大规模的问题吗?例如,使用fModifySurface :: Surface -> IO ()破坏性更新作为示例:

main = do
    w <- ... -- The window surface
    -- Do something here
    s <- someFuncGetSurface -- We get a surface here
    fModifySurface s -- Destructively update s
    blitSurface ...... -- Ignore the actual API, but destructively updates w
Run Code Online (Sandbox Code Playgroud)

上面的代码中是否有任何意外的语义?如果是这样,使用改变输入的外部函数的最佳方法是什么?

Dan*_*ner 5

我观察到f a b并且flip f b a是与β等效的术语.另一方面,这些直截了当的IO版本,即f <$> a <*> bflip f <$> b <*> a,肯定不是beta等价的; 甚至使用"解决尴尬的小队"中的等价物,这使得更多的IO行动等效,这两个术语并不等同.

在高层次上,这意味着如果你证明了纯项的行为,那么即使纯计算被用作更大程序的一部分,你也可以重复使用该证明.另一方面,没有相应的方法将关于IO术语的本地证据统一提升为关于更大型IO程序的证据; 如果您希望这样做,则必须调用一些有关您计划一起使用的特定操作的全局属性IO.

这是将尽可能多的计算提升IO到纯净世界之外的共同建议背后的推动力- 实际上,它是首先进行纯函数式编程的主要动机之一,即命令式程序不要好好组成.

但是,这些讨论都不是针对FFI或其IO操作更新其输入之一引用的值的函数.blitSurface在这方面并不比我们投入的任何"罪孽箱"更糟或更好IO.命令式程序的构成与纯粹程序不同.