Перехваченный Haskell каталог не существует, но не пустое значение - PullRequest
0 голосов
/ 29 мая 2019

С помощью 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 ]

0 голосов
/ 29 мая 2019

Проблема в том, что doesDirectoryExist "" возвращает True, но все, что находится в вашей функции getDirContent (которую вам нужно будет опубликовать, если вы хотите получить более подробный ответ), не будет работать при пропуске "".

Нет необходимости в Maybe или Either, чтобы исправить это.Просто оберните блок в конструкцию if и поместите что-то вроде putStrLn "You must enter a directory name" в else.

0 голосов
/ 29 мая 2019

Вы можете заменить строку:

doesDirectoryExist a >>= \case

с:

((&&) <$> (pure $ not $ null a) <*> doesDirectoryExist a) >>= \case

Это называется «аппликативный стиль» (если вы его не знали ;-)); Я объединяю две операции ввода-вывода, которые возвращают логическое значение, используя оператор AND (&&).

Выражение (pure $ not $ null a) проверяет, что строка не пустая, и использует «pure» для переноса чистой операции в IO (поэтому мы можем объединить ее с doDirectoryExist в выражение, которое проверяет оба условия).

EDIT:

Как заметил Джозеф, вышеприведенное выполняет 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)

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