Und*_*ren 13 haskell compiler-errors
我正在读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)
Run Code Online (Sandbox Code Playgroud)
但它不会编译,给出以下错误消息:
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;
.... }
Run Code Online (Sandbox Code Playgroud)
这里出了什么问题?为什么不编译?
ham*_*mar 26
在RWH出现后不久,异常接口被更改为支持更灵活的处理程序,其中处理程序的类型确定它将捕获哪些异常.例如,一个处理程序SomeException将捕获任何东西(通常不是一个好主意),而一个处理程序IOException只会捕获IO异常.
因此,使用"do-nothing"处理程序(例如示例中的处理程序)很容易遇到模糊问题,因为编译器无法推断出您尝试捕获的异常类型.解决此问题的一种简单方法是为处理程序函数提供类型签名.
handle ((\_ -> return Nothing) :: IOException -> IO (Maybe Integer)) $ do ...
Run Code Online (Sandbox Code Playgroud)
虽然,这可能有点冗长.另一种解决方案是专业化handle.
handleIO :: (IOException -> IO a) -> IO a -> IO a
handleIO = handle
Run Code Online (Sandbox Code Playgroud)
然后,您可以随时使用,只handleIO需要处理IO异常,而不必拼出处理程序的类型签名.
saferFileSize path = handleIO (\_ -> return Nothing) $ do ...
Run Code Online (Sandbox Code Playgroud)
第三种选择是使用ScopedTypeVariables扩展,其中(除其他外)允许您仅为函数的参数提供类型注释,允许推断其余的.
{-# LANGUAGE ScopedTypeVariables #-}
saferFileSize path = handle (\(_ :: IOException) -> return Nothing) $ do ...
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
851 次 |
| 最近记录: |