【问题标题】:Throwing exceptions in Haskell and -XDeriveDataTypeable在 Haskell 和 -XDeriveDataTypeable 中引发异常
【发布时间】:2012-01-13 16:32:14
【问题描述】:

试图在 Haskell 中抛出异常:

import Control.Exception
import Data.Typeable

data MyException = ThisException | ThatException deriving (Show, Typeable)
instance Exception MyException

data CellPos = CellPos Int Int deriving (Show, Read)

test :: String -> IO CellPos
test str = do
{
if length str == 0
then
    throw ThisException;
else
    return (CellPos 0 0);
}

编译器说:

Can't make a derived instance of `Typeable MyException':
  You need -XDeriveDataTypeable to derive an instance for this class
In the data type declaration for `MyException'

我该如何解决?

你能不能写下我在调用测试函数时如何捕捉到这样的异常?

【问题讨论】:

    标签: haskell


    【解决方案1】:

    您收到此错误是因为您尝试为您的数据类型派生 Typeable 类的实例(使用 deriving (Show, Typeable);异常类型需要 Typeable 实例),但这在标准的 Haskell;你需要一个 GHC 扩展来做到这一点。

    您可以手动编写一个 Typeable 实例,但使用 DeriveDataTypeable 实际上是推荐的方法。要启用扩展,您可以输入:

    {-# LANGUAGE DeriveDataTypeable #-}
    

    在源文件的顶部。在命令行上传递-XDeriveDataTypeable 也可以,但不推荐;最好在文件顶部记录您使用的语言扩展名,它还简化了编译,因为您不必记住标志。 (它还隔离了需要它们的文件的扩展。)

    此外,您应该在test 的定义中将throw 替换为throwIO,就像在IO monad 中的guarantees the correct ordering 一样。

    你也应该添加

    import Prelude hiding (catch)
    

    在您的导入之上,因为 Prelude 的 catch 用于旧的异常处理机制,否则当您尝试捕获异常时会与 Control.Exception 发生冲突。

    捕获异常很简单;你只需使用catch:

    example :: IO ()
    example = do
      result <- test "hello" `catch` handler
      ...
      where handler ThisException = putStrLn "Oh no!" >> exitFailure
            handler ThatException = putStrLn "Yikes!" >> exitFailure
    

    foo `catch` bar 语法与catch foo bar 相同;它适用于任何函数。)

    请注意,您的异常处理程序必须具有与您正在运行的操作相同的返回类型;你可以return 一个合适的CellPos,通过将异常传递给throwIO 使异常冒泡到下一个处理程序(可能是全局异常处理程序,它只是打印异常并停止程序),或者从程序中逃脱以其他方式,例如本例中的System.Exit.exitFailure

    【讨论】:

    • 谢谢你!你能不能写一下我在调用测试函数时如何捕捉到这样的异常?
    【解决方案2】:

    要么在命令行传入-XDeriveDataTypeable,要么放行

    {-# LANGUAGE DeriveDataTypeable #-}
    

    在文件的顶部。这些方法中的任何一个都指定了 GHC 派生 Data 和 Typeable 实例所需的语言扩展。我更喜欢第二种方法,因为它将扩展的范围限制在需要它的文件中。

    【讨论】:

      猜你喜欢
      • 2018-05-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-25
      • 2015-06-02
      • 1970-01-01
      • 2014-10-25
      相关资源
      最近更新 更多