С 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
0
Madderote 29 Май 2019 в 09:18

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)

-2
typedfern 29 Май 2019 в 21:40

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

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

0
Joseph Sible-Reinstate Monica 29 Май 2019 в 12:20