Ashot Bes
Ashot Bes

Reputation: 39

How to convert [(Data.Text.Internal.Text,Data.Text.Internal.Text)] -> Text

I make a weather program whose essence is very simple: the user enters the language in which the program will work, the city and date, and then I check it all. But when the user enters the correct city but with a small letter, the program gives an error, although the city is entered correctly

I now about toLower function, but i can't use it because of i get a pair of cities in type [(Text,Text)]

    let pairsOfCityNames  = [ let names = T.splitOn (",") twoNames
                                    [nameForHuman, nameForServer] = L.filter (not . T.null) (names)
                               in (nameForHuman, nameForServer)
                             | twoNames <- cityNames 
                             ]
          (allNamesForHumans, _) = unzip pairsOfCityNames

And i get something like:

[ ("Aragatsotn", "Aragatsotn")
, ("Ararat", "Ararat")
, ("Armavir", "Armavir")
, ("Dilijan", "Dilijan")
, ("Gegharkunik", "Gegharkunik")
, ("Gyumri", "Gyumri")
, ("Kotayk", "Kotayk")
, ("Shirak", "Shirak")
, ("Syunik", "Syunik")
, ("Vanadzor", "Vanadzor")
, ("Yerevan", "Yerevan")
]

I want when the user enters the correct city but with a small letter, the program works

And how i check it:

  cityFromUser <- TIO.getLine
  let lovercaseForCity = T.toLower cityFromUser
  cityNameForServer <- case L.lookup lovercaseForCity pairsOfCityNames of 
        Nothing -> do
            TIO.putStrLn $ messageErrorWrongCity phrasesForUser
            exitFailure 
        Just cityNameForServer -> return cityNameForServer
    TIO.putStrLn cityNameForServer 

Upvotes: 0

Views: 89

Answers (1)

sshine
sshine

Reputation: 16145

If I understand correctly, this list of pairs is meant to convert "ararat" into "Ararat" to compensate for the user's lack of Title Case, while the server you communicate with only accepts one capitalisation of a given city name.

But I could be wrong in this understanding.

You could use Data.Text.toTitle:

do cityFromUser <- T.toTitle <$> TIO.getLine
   ...

Since you're dealing with input sanitation, you may also want to T.strip leading and trailing whitespace from what the user entered. With T.toTitle you could instead of a list of pairs use a Data.Set of valid city names for the server:

import           Data.Set (Set)
import qualified Data.Set as Set

type CityName = Text

validCityNames :: Set CityName
validCityNames = Set.fromList
  [ "Aragatsotn"
  , "Ararat"
  , "Armavir"
  , "Dilijan"
  , "Gegharkunik"
  , "Gyumri"
  , "Kotayk"
  , "Shirak"
  , "Syunik"
  , "Vanadzor"
  , "Yerevan"
  , ...
  ]

getValidCityNameFromUser :: IO (Maybe CityName)
getValidCityNameFromUser = do
  cityNameFromUser <- T.toTitle . T.strip <$> TIO.getLine
  if Set.member cityNameFromUser validCityNames
    then return (Just cityNameFromUser)
    else do
      TIO.putStrLn $ messageErrorWrongCity phrasesForUser
      exitFailure

Upvotes: 2

Related Questions