简体   繁体   English

如何在haskell中实现withFile

[英]How withFile is implemented in haskell

Following a haskell tutorial , the author provides the following implementation of the withFile method: haskell教程之后 ,作者提供了withFile方法的以下实现:

withFile' :: FilePath -> IOMode -> (Handle -> IO a) -> IO a  
withFile' path mode f = do  
    handle <- openFile path mode   
    result <- f handle  
    hClose handle  
    return result  

But why do we need to wrap the result in a return ? 但为什么我们需要将result包装return Doesn't the supplied function f already return an IO as can be seen by it's type Handle -> IO a ? 提供的函数f是否已经返回IO因为它的类型Handle -> IO a

You're right: f already returns an IO , so if the function were written like this: 你是对的: f已经返回一个IO ,所以如果函数是这样编写的:

withFile' path mode f = do  
    handle <- openFile path mode   
    f handle

there would be no need for a return. 没有必要返回。 The problem is hClose handle comes in between, so we have to store the result first: 问题是hClose handle介于两者之间,所以我们必须先存储结果:

result <- f handle

and doing <- gets rid of the IO . 并做<-摆脱IO So return puts it back. 所以return把它放回去。

This is one of the tricky little things that confused me when I first tried Haskell. 当我第一次尝试Haskell时,这是让我困惑的棘手小事之一。 You're misunderstanding the meaning of the <- construct in do-notation. 你误解了<-构造在do-notation中的含义。 result <- f handle doesn't mean "assign the value of f handle to result "; result <- f handle并不意味着“将f handle的值赋给result ”; it means "bind result to a value 'extracted' from the monadic value of f handle " (where the 'extraction' happens in some way that's defined by the particular Monad instance that you're using, in this case the IO monad). 它意味着“将result绑定到从f handle的monadic值中提取的值”(其中'extract'以某种方式发生,由您正在使用的特定Monad实例定义,在本例中为IO monad)。

Ie, for some Monad typeclass m, the <- statement takes an expression of type ma in the right hand side and a variable of type a on the left hand side, and binds the variable to a value. 即,对于一些Monad类型类m, <-语句在右侧采用类型为ma的表达式,在左侧采用类型a的变量,并将该变量绑定到一个值。 Thus in your particular example, with result <- f handle , we have the types f result :: IO a , result :: a and return result :: IO a . 因此,在您的特定示例中,使用result <- f handle ,我们有类型f result :: IO aresult :: areturn result :: IO a

PS do-notation has also a special form of let (without the in keyword in this case!) that works as a pure counterpart to <- . PS do-notation还有一种特殊形式的let (在这种情况下没有in关键字!),它作为<-的纯粹对应物。 So you could rewrite your example as: 所以你可以将你的例子重写为:

withFile' :: FilePath -> IOMode -> (Handle -> IO a) -> IO a  
withFile' path mode f = do  
    handle <- openFile path mode   
    let result = f handle  
    hClose handle  
    result

In this case, because the let is a straightforward assignment, the type of result is IO a . 在这种情况下,因为let是一个简单的赋值, result的类型是IO a

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM