为什么这不会捕获转换conv B3
的异常?!
import qualified Control.Monad.Catch as E
data A = A1|A2 deriving (Enum, Show)
data B = B1|B2|B3 deriving (Enum, Show)
conv b = safeConv
where
catchError e = Left e
safeConv = (Right $ (toEnum $ fromEnum b :: A)) `E.catch` catchError
我得到了:
Right *** Exception: toEnum{A}: tag (2) is outside of enumeration's range (0,1)
CallStack (from HasCallStack):
error, called at xxx.hs:227:26 in main:Main
答案 0 :(得分:1)
Haskell异常与Java或C ++略有不同:" true"例外工作在IO
monad中,然后通过纯粹的方式模仿异常,如ExceptT
中所述。
toEnum
函数抛出第一种 - IO
异常, - 无法在纯代码中捕获。他们飞到最近的IO
地方,在你的情况下显然是GHCi。
为了捕获此类异常,您首先需要通过Control.Exception.evaluate
将投掷表达式包装在IO
中。然后,您可以使用catch
捕获此类异常,或者,如果您只想将其转换为Either exception A
(正如您似乎正在做的那样),那么就有一个应用程序! - 它被称为try
。
此外,在使用catch
或try
时,您需要指定您尝试捕获的异常的特定类型。但it is possible to catch all exceptions无论使用存在类型SomeException
而无论类型如何。
所以,结束所有这些,我们得到这个代码:
import qualified Control.Exception as E
data A = A1|A2 deriving (Enum, Show)
data B = B1|B2|B3 deriving (Enum, Show)
conv :: Enum b => b -> IO (Either E.SomeException A)
conv b = E.try . E.evaluate . toEnum $ fromEnum b
注意1 :conv
上的类型注释是必要的,以便将E.SomeException
指定为要捕获的异常类型。没有它,GHC会抱怨异常的类型不明确。
注意2 :由于conv
上的类型注释已指定目标类型A
,因此不再需要toEnum $ fromEnum b
上的类型注释。
注意3 :我已将Control.Monad.Catch
的导入替换为Control.Exception
,因为evaluate
和SomeException
位于@ConfigurationProperties(prefix = "spring.datasource")
@Bean
public DataSource dataSource(){
byte[] encryptedFile = fileRetriever.getFile(bucket, key);
String unencryptedJson = fileDecrypter.decryptFile(encryptedFile);
JSONParser parser = new JSONParser();
JSONObject jsonObject = null;
try{
jsonObject = (JSONObject) parser.parse(unencryptedJson);
}catch (Exception ex){
log.error(ex.getMessage());
}
String password = (String)jsonObject.get("password");
DataSource ds = DataSourceBuilder
.create()
.url(url)
.username(userName)
.password(password)
.build();
return ds;
}
之内
答案 1 :(得分:-1)
如果有人需要解决方案,我会留在这里。为了保持功能纯净,转换应该是:
unsafeConvEnum :: (Enum a, Enum b) => a -> b
unsafeConvEnum = toEnum . fromEnum
convEnum :: (Enum a, Enum b) => a -> Maybe b
convEnum e = unsafePerformIO conv'
where onError (_::SomeException) = pure Nothing
conv' = (Just <$> evaluate (unsafeConvEnum e)) `catch` onError
没有任何IO:)