为什么hSetBuffering不返回新句柄而不是更改给定的句柄?

时间:2017-11-11 07:07:00

标签: haskell

在Haskell中,我们尝试通过不改变变量或传递参数来以不可变的方式编写大部分代码,而是从旧的代码中创建一个具有所需更改的新值。

main = do   
withFile "something.txt" ReadMode (\handle -> do  
    hSetBuffering handle $ BlockBuffering (Just 2048)  
    contents <- hGetContents handle  
    putStr contents)  

然后是什么原因是hSetBuffering,一个接受句柄并设置其缓冲模式的函数,改变传递的handle本身而不是返回一个具有所需缓冲模式的新句柄?

1 个答案:

答案 0 :(得分:6)

使用常规Haskell值,保留旧版本的值没有问题。但是,Handle是对操作系统分配的可变资源的引用,以及进位状态。在调用返回新hSetBuffering的{​​{1}}版本之后,{em>早期版本的Handle仍会出现什么情况?他们应该反映变化吗?如果答案是肯定的,则Handle的新句柄返回版本有点谎言。

如果类型系统在调用函数后以某种方式禁止保留hSetBuffering的旧版本,则此hSetBuffering的新句柄返回版本可以正常工作。它可以通过强制执行约束来实现:接收Handle作为参数的函数只能使用该参数一次,而像Handle这样的“复制”句柄的函数是不允许

有一个(尚未接受的)proposal扩展Haskell,具有强制执行此类限制的能力。事实上,文件操作是一个激励性的例子。从论文的第2.3节开始:

dup :: Handle -> (Handle,Handle)

根据此提案,我们在任何时候都只能拥有type File openFile :: FilePath → IOL 1 File readLine :: File ⊸ IOL 1 (File,Unrestricted ByteString) closeFile :: File ⊸ IOL ω () 的单个版本。 File使closeFile的引用不可用,因此我们无法关闭已经关闭的文件。每个读取操作都采用先前版本的File并返回一个新的读取数据。 File的类型如下:

hSetBuffering