如何转换 [(Data.Text.Internal.Text,Data.Text.Internal.Text)] -> 文本

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

我制作了一个天气程序,其本质非常简单:用户输入程序运行的语言、城市和日期,然后我检查所有内容。但是当用户输入正确的城市但带有小写字母时,程序报错,虽然城市输入正确

我现在正在使用 toLower 函数,但我无法使用它,因为我得到了一对 [(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

我得到类似的东西:

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

我希望当用户输入正确的城市但带有小写字母时,程序可以运行

以及我如何检查它:

  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 

如果我没理解错的话,这个配对列表是为了将 "ararat" 转换成 "Ararat" 以弥补用户缺少 Title Case,而您与之通信的服务器只接受一个大写给定的城市名称。

但我的理解可能是错误的。

您可以使用 Data.Text.toTitle:

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

由于您要处理输入卫生问题,您可能还需要 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 服务器的有效城市名称:

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