【发布时间】:2016-01-02 17:23:25
【问题描述】:
当我在haskell中阅读SDL的文档时,我发现一些函数不可避免地会修改它的输入。例如,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
上面的代码中是否有任何意想不到的语义?如果是这样,利用改变输入的外部函数的最佳方法是什么?
【问题讨论】:
-
严格来说,这些都不是“功能”。
-
好的,命令意义上的“函数”。
-
只要所有外部函数都返回
IO SomeType,就不会破坏任何基本属性。你的情况与打电话有很大不同吗?writeIORef更新可变变量?后者是“安全的”,即使它可以被滥用来编写单一的代码。 -
问题是,外部函数就像
f (type* src, type* dest),而dest的内容明显改变了。所以如果我调用f a,它只会返回a被修改 -
Haskell 中的所有值都是不可变的,因此没有函数修改其输入。但是,某些值是(或包含)对内容可能更改的单元格的引用。但是更改这些单元格的内容并不会修改引用,就像更改文件的内容会修改其文件名一样。所以从语言的角度来看是没有问题的。当然,有时对涉及可变状态的系统进行推理可能会更加困难。
标签: haskell functional-programming sdl monads purely-functional