Почему `first` из Data.Bifunctor не преобразует это значение
В следующих:
import Data.Bifunctor
import qualified Data.ByteString.Lazy.UTF8 as BLU
safeReadFile :: FilePath -> ExceptT Text IO Text
safeReadFile p = (lift $ doesFileExist p) >>= bool (throwError "File does not exist") (lift $ pack <$> readFile p)
safeDecodeJSONFile :: FromJSON a => Text -> FilePath -> ExceptT Text IO a
safeDecodeJSONFile t f = do
contents <- safeReadFile f
tryRight $ first (\x -> pack (x ++ (unpack t))) (eitherDecode (BLU.fromString (unpack contents)))
Когда я бегу runExceptT $ safeDecodeJSONFile "something" "nonExistantFile.json"
Я ожидаю получить Left "Does not exist something"
но вместо этого я просто получаю Left "Does not exist"
- Я знаю, что функция, которую я передаю first
выполняется, так как без pack
GHC жалуется, что тип (eitherDecode (BLU.fromString (unpack contents)))
является ExceptT String IO a
вместо ExceptT Text IO a
- так почему не конкатенация от ++
тоже бывает?
1 ответ
Вы написали
safeDecodeJSONFile t f = do
contents <- safeReadFile f
tryRight $ ...
Monad
экземпляр для ExceptT
сдается, как только он ударяет Left
возвращая именно это. Так что tryRight ...
никогда не бывает Вы должны справиться с Left
случай явно, возможно, с использованием catchError
,
Пока мы на этом, все еще есть проблема. Ты пишешь
safeReadFile :: FilePath -> ExceptT Text IO Text
safeReadFile p = (lift $ doesFileExist p) >>= bool (throwError "File does not exist") (lift $ pack <$> readFile p)
К сожалению, это не надежно. Во-первых, файл не существует, это только одна из причин, по которой он может потерпеть неудачу - могут быть ошибки разрешения, проблемы с сетью для сетевых файловых систем, ошибки устройства, если файл не является обычным файлом, и т. Д. Во-вторых, кто-то другой может удалить файл между временем проверки его существования и временем, когда вы пытаетесь его прочитать. Обычный совет при попытке разобраться с файлами - не проверять сначала. Просто прочитайте файл и перехватите все исключения, используя catch
или подобное в Control.Exception
или обертки вокруг них