代码之家  ›  专栏  ›  技术社区  ›  luntain

不明确的类型变量错误消息

  •  21
  • luntain  · 技术社区  · 16 年前

    我不认为这是一个错误,但我有点困惑,为什么这不工作。一个额外的问题是为什么它提到变量e?没有变量e。

        Prelude> :m +Control.Exception
        Prelude Control.Exception> handle (\_-> return "err") undefined
    
        <interactive>:1:0:
            Ambiguous type variable `e' in the constraint:
              `Exception e'
                arising from a use of `handle' at <interactive>:1:0-35
            Probable fix: add a type signature that fixes these type variable(s)
        Prelude Control.Exception> 
    

    显然它在ghci6.8中运行良好,我使用的是6.10.1。

    class C a                                                                                                     
    
    foo :: C a => (a -> Int)-> Int                                                                                
    foo _ = 1                                                                                                     
    
    arg :: C a => a -> Int                                                                                        
    arg _ = 2                                                                                                     
    
    bar :: Int                                                                                                    
    bar = foo arg
    

    [1 of 1] Compiling Main             ( /tmp/foo.hs, interpreted )
    
    /tmp/foo.hs:12:10:
        Ambiguous type variable `a' in the constraint:
          `C a' arising from a use of `arg' at /tmp/foo.hs:12:10-12
        Probable fix: add a type signature that fixes these type variable(s)
    Failed, modules loaded: none.
    Prelude Control.Exception> 
    
    5 回复  |  直到 13 年前
        1
  •  12
  •   Alain O'Dea    12 年前

    Control.Exception.handle 是:

    handle :: Exception e => (e -> IO a) -> IO a -> IO a
    

    (\_ -> return "err") 不是类型 e -> IO a 哪里 e Exception . 清澈如泥?很好。现在我将提供一个实际有用的解决方案:)

    电子 应该是 Control.Exception.ErrorCall undefined 使用 error 哪个扔 ErrorCall 例外情况

    使用 你可以这样定义 handleError :

    handleError :: (ErrorCall -> IO a) -> IO a -> IO a
    handleError = handle
    

    它本质上是一个别名 具有 固定为 错误呼叫 那是什么 投掷。

    磨合时是这样的 GHCi 7.4.1 :

    ghci> handleError (\_ -> return "err") undefined
    "err"
    

    处理所有异常 handleAll 函数可以编写如下:

    handleAll :: (SomeException -> IO a) -> IO a -> IO a
    handleAll = handle
    

    捕获所有异常的结果在本节中有很好的描述 Control.Exception 文档:

    通过使用 SomeException

    catch f (\e -> ... (e :: SomeException) ...)
    

    然而,这通常不是你想做的!

    例如,假设您想读取一个文件,但如果它不存在,则继续,就像它包含一样 "" . 您可能想捕获所有异常并返回 "" UserInterrupt "" . 类似地,如果另一个线程试图终止读取文件的线程,那么 ThreadKilled

    相反,您应该只捕获您真正想要的异常。在这种情况下,这可能比“任何IO异常”都更具体;权限错误也可能需要不同的处理方式。相反,您可能需要以下内容:

     e <- tryJust (guard . isDoesNotExistError) (readFile f)
     let str = either (const "") id e
    

    有时您确实需要捕获任何类型的异常。然而,在大多数情况下,这只是为了让您可以进行一些清理;实际上您对异常本身并不感兴趣。例如,如果您打开一个文件,那么您想再次关闭它,不管处理文件是正常执行还是引发异常。但是,在这些情况下,您可以使用如下函数 bracket , finally onException ,它实际上从不向您传递异常,而只是在适当的点调用清理函数。

    catch 一些例外

    资料来源: http://www.haskell.org/ghc/docs/latest/html/libraries/base/Control-Exception.html#g:4

        2
  •  10
  •   Norman Ramsey    16 年前

    handle

    : nr@homedog 620 ; ghci
    GHCi, version 6.8.2: http://www.haskell.org/ghc/  :? for help
    Loading package base ... linking ... done.
    Prelude> :m +Control.Exception
    Prelude Control.Exception>  handle (\_ -> return "err") undefined
    "err"
    Prelude Control.Exception> 
    

    好吧,也许我最终能把这件事做好。我想问题是 单态限制,但是您遇到了读/显示问题的一个实例:您正在提供处理某种类型的异常,在新版本的“handle”中,有多种类型的异常,并且该异常的类型不会出现在您的结果中。所以编译器无法知道 哪一个

    Prelude Control.Exception> let alwaysError :: SomeException -> IO String; alwaysError = \_ -> return "err"
    Prelude Control.Exception> handle alwaysError undefined
    "err"
    

    顺便说一句,使用 在GHC库中,文档未按照6.10进行编译。我已经提交了一份错误报告。

        3
  •  3
  •   Thomas    15 年前

    解决方法是使用 Control.OldException 在ghc 6.10中。*而不是 Control.Exception .

        4
  •  2
  •   gmfawcett gmfawcett    15 年前

    SomeException -> IO x

    import Control.Exception
    let f _ = putStrLn "error" :: SomeException -> IO () 
    in handle f undefined 
    
        5
  •  1
  •   Waquo    16 年前

    “异常e”可能来自“handle”的类型签名。

    The documentation 说:

    handle :: Exception e => (e -> IO a) -> IO a -> IO a
    

    在ghc6.8中,它曾经是不同的,这可以解释为什么我没有得到那个错误。

    handle :: (Exception -> IO a) -> IO a -> IO a
    

    试试这个:

    let f _ = return "err"
    handle f undefined
    

    http://www.haskell.org/haskellwiki/Monomorphism_restriction