С LambdaCase
я могу отфильтровать, если каталог не существует. Однако: если пользователь получает запрос и нажимает клавишу ввода (пусто), я все равно получаю исключение. Я думаю, что Maybe
или Either
могут помочь мне здесь, но мне трудно понять, как это настроить.
{-# LANGUAGE LambdaCase #-}
import System.Directory
import System.IO
dirExist = do
a <- prompt "Directory:> "
doesDirectoryExist a >>= \case
True -> getDirContent a
_ -> putStrLn "Directory does not exist or invalid value specified."
getDirContent :: FilePath -> IO ()
getDirContent dir = do
result <- getDirectoryContents dir
mapM_ putStrLn $ result
prompt :: String -> IO String
prompt x = do
putStr x
a <- getLine
return a
2 ответа
Вы можете заменить строку:
doesDirectoryExist a >>= \case
С:
((&&) <$> (pure $ not $ null a) <*> doesDirectoryExist a) >>= \case
Это называется «аппликативный стиль» (если вы его не знали ;-)); Я объединяю две операции ввода-вывода, которые возвращают логическое значение, используя оператор AND (&&).
Выражение (pure $ not $ null a) проверяет, что строка не пустая, и использует «pure» для поднятия чистой операции в IO (поэтому мы можем объединить ее с doDirectoryExist в выражение, которое проверяет оба условия).
РЕДАКТИРОВАТЬ:
Как заметил Джозеф, вышеприведенное выполняет doDirectoryExist независимо от того, нужно оно или нет; вы обычно хотите этого избежать (если только вы не полагаетесь на его побочные эффекты); вы можете избежать этого с предложением Брэдра; Вы также можете сделать это:
(if null a then pure False else doesDirectoryExist a) >>= \case
В качестве альтернативы, так как вам не нравится нотация if-then-else (как и я):
(case null a of True -> pure False; False -> doesDirectoryExist a) >>= \case
Не совсем чище, хотя; Вы можете импортировать Data.Bool и сделать это:
-- import Data.Bool
(bool (doesDirectoryExist a) (pure False) $ null a) >>= \case
(«bool» - это просто более функциональная нотация для старого доброго if-then-else)
Проблема в том, что doesDirectoryExist ""
возвращает True
, но все, что есть в вашей функции getDirContent
(которую вам нужно будет опубликовать, если вы хотите получить более подробный ответ), не будет работать при пропуске ""
.
Нет необходимости в Maybe
или Either
, чтобы это исправить. Просто оберните блок в if
конструкцию и поместите что-то вроде putStrLn "You must enter a directory name"
в else
.
Похожие вопросы
Новые вопросы
haskell
Haskell - это функциональный язык программирования, отличающийся строгой статической типизацией, отложенной оценкой, обширной поддержкой параллелизма и параллелизма и уникальными возможностями абстракции.