为什么 Data.Bifunctor 中的 `first` 不转换这个值
Why doesn't `first` from Data.Bifunctor transform this value
在下面:
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
- 那么为什么 ++
的连接不是也会发生?
你写了
safeDecodeJSONFile t f = do
contents <- safeReadFile f
tryRight $ ...
ExceptT
的 Monad
实例在遇到 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
中的类似内容或围绕它们的包装器
捕获任何异常
在下面:
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
- 那么为什么 ++
的连接不是也会发生?
你写了
safeDecodeJSONFile t f = do
contents <- safeReadFile f
tryRight $ ...
ExceptT
的 Monad
实例在遇到 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
中的类似内容或围绕它们的包装器