【问题标题】:Ambiguous type arising from try由 try 引起的模棱两可的类型
【发布时间】:2021-05-08 11:22:06
【问题描述】:

我试图在打开文件时进行一些错误处理,以确保文件存在/可读。这是我的尝试:

init struct = do
    str <- try $ readFile (filePath struct)
    case str of
        Left exception -> print exception
        Right content -> execute content struct

(Struct 是一种数据结构,我在其中保存文件路径和其他变量)。 我收到此错误:

由于使用“try”而产生的模棱两可的类型变量“a0” 防止约束“(异常 a0)”被解决。 可能的解决方法:使用类型注释来指定“a0”应该是什么。

但我就是不明白如何解决它。

【问题讨论】:

    标签: haskell


    【解决方案1】:

    这是因为try :: ... -&gt; IO (Either e a) 的结果有一个用于异常e 的类型参数,而您只需将其放入可以处理所有类型的print 中(只要e 在@987654326 中@) - 所以对于编译器来说,中间 e 需要是什么类型并不明显。

    这与show . read 非常相似——应该是String -&gt; String 类型,但read 应该做什么?阅读IntFloat - 有什么不同吗?


    解决此问题的最简单方法是 IMO 使用类型应用程序:

    {-# LANGUAGE TypeApplications #-}
    
    init struct = do
        str <- try @IOException $ readFile (filePath struct)
        case str of
            Left exception -> print exception
            Right content -> execute content struct
    

    当然你可以在任何你想要的地方添加类型注解

    str <- try $ readFile (filePath struct) :: IO (Either IOException MyStruct)
    

    等等

    【讨论】:

    • 嗯,我不知道存在类型应用程序,谢谢。我实际上并没有尝试打印异常,而是在 readFile 出现任何问题时调用另一个函数退出程序,添加类型注释效果很好。谢谢!
    • SomeException 是矫枉过正,IMO,甚至 the docs do not recommend it:它包括除以零、用户 Ctrl-C 和其他几个通常不想处理的异常。在这种情况下,IOException 看起来更明智。
    • 当然 - 我会很乐意改变它
    • 感谢Carsten的解释,现在很清楚了!我每天都在学习有关 Haskell 的新知识
    猜你喜欢
    • 2011-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-18
    • 1970-01-01
    相关资源
    最近更新 更多