【问题标题】:Haskell: Dealing With Types And ExceptionsHaskell:处理类型和异常
【发布时间】:2010-04-21 21:44:18
【问题描述】:

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

编辑:更新代码以正确反映描述。

【问题讨论】:

    标签: exception haskell types


    【解决方案1】:

    你不能去掉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
    

    你得到的是Left errorRight var,而不是NothingJust var

    【讨论】:

      【解决方案2】:

      一旦你知道任何涉及getEnv 的事情都将涉及在IO monad 中返回一个结果,那么你的基本方法就没有问题了。虽然您可以使用System.IO.Error(我会),但按照您的方式编写它同样有效且具有指导意义。但是,您确实使用了比惯用的 Haskell 更多的标点符号:

      getEnvVar x = (Just `fmap` getEnv x) `catch` const (return Nothing)
      

      getEnvVar x = getEnv x `catch` const (return "")
      

      【讨论】:

        【解决方案3】:

        你也可以试试

        import System.Environment
        getEnvVar :: String -> IO (Maybe String)
        getEnvVar x = getEnvironment >>= return . lookup x
        

        或更长一点,但可能更容易理解:

        getEnvVar x = do
            fullEnvironment <- getEnvironment
            return (lookup x fullEnvironment)
        

        如果您不介意全程浏览整个环境。

        【讨论】:

        • 这里没有必要使用单子的力量; getEnvVar x = fmap (lookup x) getEnvironment 也同样有效,并且确实需要使用 return
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-30
        • 1970-01-01
        • 1970-01-01
        • 2017-12-02
        • 1970-01-01
        相关资源
        最近更新 更多