gpt4 book ai didi

compiler-errors - "handle"函数和 Real World Haskell

转载 作者:行者123 更新时间:2023-12-03 23:12:43 27 4
gpt4 key购买 nike

我正在阅读 RWH,我已经来到了第 9 章。它介绍了以下一段代码:

import System.IO
import Control.Exception

saferFileSize :: FilePath -> IO (Maybe Integer)
saferFileSize path = handle (\_ -> return Nothing) $ do
h <- openFile path ReadMode
size <- hFileSize h
hClose h
return (Just size)

但是它不会编译,并给出以下错误消息:
test.hs:5:22:
Ambiguous type variable `e0' in the constraint:
(Exception e0) arising from a use of `handle'
Probable fix: add a type signature that fixes these type variable(s)
In the expression: handle (\ _ -> return Nothing)
In the expression:
handle (\ _ -> return Nothing)
$ do { h <- openFile path ReadMode;
size <- hFileSize h;
hClose h;
return (Just size) }
In an equation for `saferFileSize':
saferFileSize path
= handle (\ _ -> return Nothing)
$ do { h <- openFile path ReadMode;
size <- hFileSize h;
hClose h;
.... }

这里出了什么问题?为什么编译不出来?

最佳答案

在 RWH 出现后不久,异常接口(interface)被更改为支持更灵活的处理程序,其中处理程序的类型决定了它将捕获哪些异常。例如。接受 SomeException 的处理程序将捕获任何东西(通常不是一个好主意),而处理程序需要 IOException只会捕获 IO 异常。

因此,对于示例中的“无所事事”处理程序,很容易遇到模棱两可的问题,因为编译器无法推断您要捕获的异常类型。解决此问题的一种简单方法是为您的处理程序函数提供类型签名。

handle ((\_ -> return Nothing) :: IOException -> IO (Maybe Integer)) $ do ...

不过,这可能有点冗长。另一种解决方案是专门化 handle .
handleIO :: (IOException -> IO a) -> IO a -> IO a
handleIO = handle

然后,您可以使用 handleIO每当您想处理 IO 异常时,无需拼出处理程序的类型签名。
saferFileSize path = handleIO (\_ -> return Nothing) $ do ...

第三种选择是使用 ScopedTypeVariables扩展,它(除其他外)允许您仅为函数的参数提供类型注释,从而允许推断其余部分。
{-# LANGUAGE ScopedTypeVariables #-}
saferFileSize path = handle (\(_ :: IOException) -> return Nothing) $ do ...

关于compiler-errors - "handle"函数和 Real World Haskell,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10578572/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com