[英]How withFile is implemented in haskell
在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
但为什么我们需要将result
包装return
? 提供的函数f
是否已经返回IO
因为它的类型Handle -> IO a
?
你是对的: f
已经返回一个IO
,所以如果函数是这样编写的:
withFile' path mode f = do
handle <- openFile path mode
f handle
没有必要返回。 问题是hClose handle
介于两者之间,所以我们必须先存储结果:
result <- f handle
并做<-
摆脱IO
。 所以return
把它放回去。
当我第一次尝试Haskell时,这是让我困惑的棘手小事之一。 你误解了<-
构造在do-notation中的含义。 result <- f handle
并不意味着“将f handle
的值赋给result
”; 它意味着“将result
绑定到从f handle
的monadic值中提取的值”(其中'extract'以某种方式发生,由您正在使用的特定Monad实例定义,在本例中为IO monad)。
即,对于一些Monad类型类m, <-
语句在右侧采用类型为ma
的表达式,在左侧采用类型a
的变量,并将该变量绑定到一个值。 因此,在您的特定示例中,使用result <- f handle
,我们有类型f result :: IO a
, result :: a
并return result :: IO a
。
PS do-notation还有一种特殊形式的let
(在这种情况下没有in
关键字!),它作为<-
的纯粹对应物。 所以你可以将你的例子重写为:
withFile' :: FilePath -> IOMode -> (Handle -> IO a) -> IO a
withFile' path mode f = do
handle <- openFile path mode
let result = f handle
hClose handle
result
在这种情况下,因为let
是一个简单的赋值, result
的类型是IO a
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.