Haskell:处理类型和异常

时间:2010-04-21 12:36:55

标签: exception haskell types

我想知道捕获和处理异常的“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方式?

编辑:更新了代码以正确反映说明。

3 个答案:

答案 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

取代NothingJust var代替Left errorRight 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)

如果你不介意整个环境都在整个环境中。