带递归的 Monad Transformer
Monad Transformer with recursion
当我想载入一个 bmp 文件时,我用:
loadBMP :: String -> IO Picture
如果不确定给定路径是否存在,可以执行以下操作:
saveLoad :: String -> IO Picture
saveLoad str = do
b <- doesFileExist str
if b then loadBMP str
else return Blank
另一种方式也可以;使用 monad 转换器:
saveLoadM :: String -> MaybeT IO Picture
saveLoadM s = do
b <- lift $ doesFileExist s
if b then do
p <- lift$ loadBMP s
return p
else MaybeT $ return Nothing
但是您将如何处理文件列表?
test ::[String] -> ListT IO Picture
test [] = ListT $ return []
test (x:xs) = do
b <- lift $ doesFileExist x
if b then do
p <- lift$ loadBMP x
return p -- would yield a simple [p]
-- therefore:
p : test xs -- wrong -> not working
else test xs
您可以使用 the witherable
package,像这样:
import Witherable
test :: [String] -> IO [Picture]
test = wither $ \x -> do
b <- doesFileExist x
if b then do
p <- loadBMP x
return $ Just p
else return Nothing
为了直观地了解 wither
的含义,想象一下如果它被命名为 mapMaybeM
。
你只需要 fmap
.
test :: [String] -> IO [Picture]
-- this bit as before...
if b then do
p <- loadBMP x
(p:) <$> test xs
else test xs
但是你不应该这样使用doesFileExist
。相反,加载位图并在文件不存在时捕获异常;这可以防止竞争条件。
test (x:xs) = do
imgE <- try (loadBMP x)
case imgE of
Right img -> (img:) <$> test xs
Left err | isDoesNotExistError err -> test xs
| otherwise -> throwIO err -- reraise other exceptions
如果您不介意扩展,我觉得匿名案例很适合这里。
test (x:xs) = try (loadBMP x) >>= \case
Right img -> ...
Left err | ...
| ...
当我想载入一个 bmp 文件时,我用:
loadBMP :: String -> IO Picture
如果不确定给定路径是否存在,可以执行以下操作:
saveLoad :: String -> IO Picture
saveLoad str = do
b <- doesFileExist str
if b then loadBMP str
else return Blank
另一种方式也可以;使用 monad 转换器:
saveLoadM :: String -> MaybeT IO Picture
saveLoadM s = do
b <- lift $ doesFileExist s
if b then do
p <- lift$ loadBMP s
return p
else MaybeT $ return Nothing
但是您将如何处理文件列表?
test ::[String] -> ListT IO Picture
test [] = ListT $ return []
test (x:xs) = do
b <- lift $ doesFileExist x
if b then do
p <- lift$ loadBMP x
return p -- would yield a simple [p]
-- therefore:
p : test xs -- wrong -> not working
else test xs
您可以使用 the witherable
package,像这样:
import Witherable
test :: [String] -> IO [Picture]
test = wither $ \x -> do
b <- doesFileExist x
if b then do
p <- loadBMP x
return $ Just p
else return Nothing
为了直观地了解 wither
的含义,想象一下如果它被命名为 mapMaybeM
。
你只需要 fmap
.
test :: [String] -> IO [Picture]
-- this bit as before...
if b then do
p <- loadBMP x
(p:) <$> test xs
else test xs
但是你不应该这样使用doesFileExist
。相反,加载位图并在文件不存在时捕获异常;这可以防止竞争条件。
test (x:xs) = do
imgE <- try (loadBMP x)
case imgE of
Right img -> (img:) <$> test xs
Left err | isDoesNotExistError err -> test xs
| otherwise -> throwIO err -- reraise other exceptions
如果您不介意扩展,我觉得匿名案例很适合这里。
test (x:xs) = try (loadBMP x) >>= \case
Right img -> ...
Left err | ...
| ...