试图在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);
}
Run Code Online (Sandbox Code Playgroud)
编译说:
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'
Run Code Online (Sandbox Code Playgroud)
我怎么解决它?
您是否还可以编写在调用测试函数时如何捕获此类异常?
ehi*_*ird 12
您收到此错误是因为您正在尝试为您的数据类型派生Typeable类的实例(带有deriving (Show, Typeable);异常类型需要Typeable实例),但这在标准Haskell中是不可能的; 你需要一个GHC扩展来做到这一点.
您可以手动编写Typeable实例,但DeriveDataTypeable实际上建议使用using .要启用扩展程序,您可以执行以下操作:
{-# LANGUAGE DeriveDataTypeable #-}
Run Code Online (Sandbox Code Playgroud)
在源文件的顶部.传递-XDeriveDataTypeable命令行也有效,但不推荐; 最好记录您在文件顶部使用的语言扩展,并且还简化了编译,因为您不必记住标志.(它还将扩展名隔离到需要它们的文件.)
此外,应更换throw同throwIO在的定义test,因为它保证了正确的顺序在IO单子.
你还应该添加
import Prelude hiding (catch)
Run Code Online (Sandbox Code Playgroud)
在你的导入之上,因为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
Run Code Online (Sandbox Code Playgroud)
(foo `catch` bar语法catch foo bar与之相同;它适用于任何函数.)
请注意,您的异常处理程序必须与您正在运行的操作具有相同的返回类型; 你可以return适当的CellPos,通过将异常气泡传递给下一个处理程序(可能是全局异常处理程序,它只是打印异常并停止程序)throwIO,或者以其他方式从程序中逃脱,就像System.Exit.exitFailure在这个例子中一样.
要么在命令行中传入-XDeriveDataTypeable,要么将行
{-# LANGUAGE DeriveDataTypeable #-}
Run Code Online (Sandbox Code Playgroud)
在文件的顶部。这些方法中的任何一个都指定 GHC 派生 Data 和 Typeable 实例所需的语言扩展。我更喜欢第二种方法,因为它将扩展的范围限制为需要它的文件。
| 归档时间: |
|
| 查看次数: |
1485 次 |
| 最近记录: |