【问题标题】:How withFile is implemented in haskellhaskell中withFile是如何实现的
【发布时间】:2011-12-19 20:21:35
【问题描述】:

按照haskell tutorial,作者提供了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 -&gt; IO a 可以看出?

【问题讨论】:

    标签: haskell


    【解决方案1】:

    你是对的:f 已经返回了一个IO,所以如果函数是这样写的:

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

    没有必要退货。问题是hClose handle介于两者之间,所以我们必须先存储结果:

    result <- f handle
    

    并且做&lt;- 摆脱IO。所以return 把它放回去了。

    【讨论】:

    • 天哪!完全错过了 sucking &lt;- 运营商!
    • 也可以是 let result = f handle; hClose handle; result 还是我再次无法理解单子?
    • @delnan 应该是do { handle &lt;- openFile mode path; hClose handle; f handle; },所以f handle 可能会抱怨句柄关闭。
    • @DanielFischer:对,脑子放个屁。生成的 IO 值(“动作”)不会仅从 let 进行评估。
    • @drozzy 另一种结局:f handle &gt;&gt;= \result -&gt; hClose handle &gt;&gt; return result。这里&gt;&gt;=是用来摆脱IO的,希望你也不要错过&gt;&gt;=。有许多不同的吸吮方式,例如&gt;=&gt; 和它们的反向对应物 =&lt;&lt;&lt;=&lt;
    【解决方案2】:

    这是我第一次尝试 Haskell 时让我感到困惑的棘手小事之一。您误解了 do-notation 中 &lt;- 构造的含义。 result &lt;- f handle 并不意味着“将f handle 的值赋值给result”;它的意思是“将result绑定到一个从f handle的单子值'提取'的值”(其中'提取'以某种方式发生,这是由您正在使用的特定Monad实例定义的,在这种情况下是IO单子)。

    即,对于某些 Monad 类型类 m,&lt;- 语句在右侧采用 m a 类型的表达式,在左侧采用 a 类型的变量,并将变量绑定到一个值.因此,在您的特定示例中,使用result &lt;- f handle,我们有f result :: IO aresult :: areturn result :: IO a 类型。

    PS do-notation 还有一种特殊形式的let(在这种情况下没有in 关键字!),它与&lt;- 完全对应。因此,您可以将示例重写为:

    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

    【讨论】:

    • 酷!我称&lt;- 为suck 运算符,因为它会从rhs 中吸取价值:-)
    猜你喜欢
    • 1970-01-01
    • 2011-02-10
    • 2012-01-18
    • 1970-01-01
    • 2014-06-12
    • 1970-01-01
    • 2013-12-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多