我想知道捕获和处理异常的“Haskell方式”。如下所示,我理解基本语法,但我不确定在这种情况下如何处理类型系统。
以下代码尝试返回请求的环境变量的值。显然,如果那个变量不存在,我想捕获异常并返回Nothing。
getEnvVar x = do {
var <- getEnv x;
Just var;
} `catch` \ex -> do {
Nothing
}
这是错误:
Couldn't match expected type `IO a'
against inferred type `Maybe String'
In the expression: Just var
In the first argument of `catch', namely
`do { var <- getEnv x;
Just var }'
In the expression:
do { var <- getEnv x;
Just var }
`catch`
\ ex -> do { Nothing }
我可以返回字符串值:
getEnvVar x = do {
var <- getEnv x;
return var;
} `catch` \ex -> do {
""
}
然而,这并不像Haskell那样。什么是Haskell方式?
编辑:更新了代码以正确反映说明。
答案 0 :(得分:7)
您无法删除IO
并在do-block中返回Maybe String
。您需要返回IO (Maybe String)
。
getEnvVar x = do {
var <- getEnv x;
return (Just var);
} `catch` \ex -> do {
return Nothing
}
为什么不使用
import qualified System.IO.Error as E
getEnvVar :: String -> IO (Either IOError String)
getEnvVar = E.try . getEnv
取代Nothing
和Just var
代替Left error
和Right var
。
答案 1 :(得分:3)
一旦你得到涉及getEnv
的任何内容将涉及在IO
monad中返回结果,那么你的基本方法没有任何问题。虽然你可以使用System.IO.Error
(我愿意),但是按照你的方式编写它是同样有效和有益的。但是,你确实使用了比Haskell使用的标点符号更多的标点:
getEnvVar x = (Just `fmap` getEnv x) `catch` const (return Nothing)
或
getEnvVar x = getEnv x `catch` const (return "")
答案 2 :(得分:1)
您也可以尝试
import System.Environment
getEnvVar :: String -> IO (Maybe String)
getEnvVar x = getEnvironment >>= return . lookup x
或者更长一些,但也许更容易理解:
getEnvVar x = do
fullEnvironment <- getEnvironment
return (lookup x fullEnvironment)
如果你不介意整个环境都在整个环境中。