Haskell: Работа с типами и исключений - PullRequest
2 голосов
/ 21 апреля 2010

Мне бы хотелось узнать «способ Haskell» для отлова и обработки исключений. Как показано ниже, я понимаю основной синтаксис, но я не уверен, что делать в этой ситуации с системой типов.

Приведенный ниже код пытается вернуть значение запрошенной переменной среды. Очевидно, что если этой переменной нет, я хочу перехватить исключение и ничего не возвращать.

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 {
    ""
}

однако, это не похоже на путь Хаскелла. Что такое путь на Хаскеле?

Редактировать: Обновлен код для правильного отражения описания.

Ответы [ 3 ]

7 голосов
/ 21 апреля 2010

Вы не можете удалить IO и вернуть Maybe String в блоке do. Вам необходимо вернуть 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.

3 голосов
/ 21 апреля 2010

Как только вы поймете, что все, что связано с getEnv, будет включать в себя возвращение результата в монаде IO, тогда в вашем базовом подходе нет ничего плохого. И хотя вы могли бы использовать System.IO.Error (и я бы это сделал), так же правильно и поучительно написать его так, как вы это сделали. Тем не менее, вы использовали немного больше знаков препинания, чем использовал бы idomatic Haskell:

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

или

getEnvVar x = getEnv x `catch` const (return "")
1 голос
/ 21 апреля 2010

Вы также можете попробовать

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

или немного дольше, но, возможно, легче следовать:

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

если вы не против проходить всю среду все время.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...