【问题标题】:Haskell type error with catch带 catch 的 Haskell 类型错误
【发布时间】:2013-11-30 14:53:29
【问题描述】:

我正在玩一些在线示例,其中一个有这样的短语:

   do ... contents <- getDirectoryContents path `catch` const (return []) 

但它不会为我编译,并给出错误:

No instance for (Exception e0) arising from a use of `catch'
The type variable `e0' is ambiguous
Possible fix: add a type signature that fixes these type variable(s)
Note: there are several potential instances:
  instance Exception NestedAtomically
    -- Defined in `Control.Exception.Base'
  instance Exception NoMethodError
    -- Defined in `Control.Exception.Base'
  instance Exception NonTermination
    -- Defined in `Control.Exception.Base'
  ...plus 7 others
In a stmt of a 'do' block:
  contents <- getDirectoryContents path `catch` const (return [])
In the expression:
  do { contents <- getDirectoryContents path
                   `catch` const (return []);

我不得不更改它以提供处理程序的类型,现在可以,但有点混乱:

contents <- getDirectoryContents path `catch` (\(SomeException e) -> const (return []) e)

所以我想知道为什么我需要进行此更改,以及这是否是最简洁的方法。 (是的,我知道我可以使用其他形式的 try、handle、...)

【问题讨论】:

    标签: exception haskell exception-handling


    【解决方案1】:

    catch 的类型为Exception e =&gt; IO a -&gt; (e -&gt; IO a) -&gt; IO a,所以(e -&gt; IO a) 是您传递const 函数结果的位置,但在这种情况下const 返回类型是(e0 -&gt; IO [])。正如你所看到的,这种类型有e0,它没有像catch中需要的那样受到限制,即e应该有Exception实例,这就是错误的意思。

    因此,从概念上讲,您将“较少约束”的东西传递到需要“更多约束”的地方。

    【讨论】:

    • 那么为什么不能将通用类型变量 e0 与 catch 类型中的多态 e 统一起来呢?并且 - 为什么它会在原始示例中起作用?
    • @guthrie:它可以统一,但 GHC 需要知道它统一在 哪个 具体类型,因为 Exception e 约束会产生不同的行为,具体取决于。这就像show undefined 可能会出现的歧义错误;不确定要使用哪个 show 函数。
    • @Antal:在我看来这有点不同,因为 show 有一个类型约束 (Show a) 必须满足才能统一,但在这种情况下,处理程序 (const) 是不受约束的,它可以取任何类型,因此可以与任何东西统一。
    • 这与:stackoverflow.com/questions/431527/… 有关,其中有人还发现句柄类型在 GHC 6.8 和 6.10 之间发生了变化,也许这就是为什么它曾经在原始代码中工作的原因。
    • @Ankur:谢谢,是的,解释清楚。有人可能会说“在需要更专业的地方传递更(太)一般的东西”。
    猜你喜欢
    • 2019-04-27
    • 2011-02-08
    • 2013-09-04
    • 2013-12-18
    • 1970-01-01
    • 2022-01-02
    • 2012-01-06
    • 1970-01-01
    相关资源
    最近更新 更多