Где я могу поймать исключение? - PullRequest
0 голосов
/ 23 октября 2018

Мой код:

{-# LANGUAGE MultiWayIf        #-}
{-# LANGUAGE OverloadedStrings #-}

module UserData where

import           Control.Exception
import           Data.Either
import           Data.Maybe
import           Data.Time         (getCurrentTime)
import           Data.Time.Clock
import           Data.Time.Format

import           Types

round' :: NominalDiffTime -> Integer
round' mark
    | mark < 0 = 0
    | mark2 > 100 = 100
    | otherwise = mark2
    where mark2 = round mark

supportedCities :: [City]
supportedCities = [Aragatsotn .. Yerevan]

getUserData :: IO (Either String (UTCTime,City))
getUserData = do
    date         <- getDateFromUser
    cityFromUser <- getCityFromUser
    if | isLeft date         -> return $ Left "error"
       | isNothing cityFromUser -> return $ Left "error"
       | otherwise      -> let [realDate] = rights [date] in return $ Right 

(realDate, fromJust cityFromUser)

getDateFromUser :: IO (Either String UTCTime)
getDateFromUser = do
  Prelude.putStrLn "Пожалуйста, укажите дату для прогноза в формате ГГГГ-ММ-ДД:"
  currentTime <- getCurrentTime
  date        <- Prelude.getLine
  let dayFromUser = parseTimeOrError True defaultTimeLocale "%Y-%m-%d %H:%M:%S" (date ++ " 12:00:00") :: UTCTime
  case dayFromUser of
    validDay -> do
          let differenceInNominalDiffTime = diffUTCTime validDay currentTime
              secondsInDay = 86400
              differenceInDays = round' $ differenceInNominalDiffTime / secondsInDay
          if differenceInDays >= 0 && differenceInDays <= 5
              then return $ Right validDay
              else return $ Left "asdasd"

getCityFromUser :: IO (Maybe City)
getCityFromUser = do
    Prelude.putStrLn "Пожалуйста, укажите один из этих марзов:"
    print [Aragatsotn .. Yerevan]
    cityFromUser <- Prelude.getLine
    let cityAsString = Prelude.map show supportedCities
    if cityFromUser `elem` cityAsString
       then return $ Just (read cityFromUser :: City)
       else return Nothing

Этот код работает.

Я получаю ошибку

Нонасколько я понимаю функцию разбора, parseTimeOrError возвращает исключение.Как и где я должен поймать это исключение?

То есть вместо исключения мне нужно показать строку

типа "извините, ваши данные неверны"

1 Ответ

0 голосов
/ 23 октября 2018

Самое простое изменение в вашей программе - использовать parseTimeM вместо parseTimeOrError.

Maybe - это один из возможных типов, которые можно заполнить для m, поэтому вы можете написать:

parseTimeM True defaultTimeLocale "%Y-%m-%d %H:%M:%S" "2018-10-23 11:41:20" :: Maybe UTCTime

В вашей программе validDay -> do может измениться на Just validDay -> do, и GHC выведет Maybe, поэтому вам не понадобится явная сигнатура типа, которую я дал выше.

...