Как я могу использовать чтение для строки, которая не заключена в двойные кавычки? - PullRequest
5 голосов
/ 15 мая 2011

Я читаю значения из in с консоли, используя readLn.

Я хотел бы написать функцию:

requestValue :: String -> IO a  
requestValue s = do  
  putStrLn $ "Please enter a new value for " ++ s   
  readLn

Я бы тогда смог сделать, например,

changeAge :: Person -> IO Person
changeAge p = do
    age' <- requestValue "age"
    return $ p { age = age'}

changeName :: Person -> IO Person
changeName p = do
    name' <- requestValue "name"
    return $ p { name = name'}

Проблема, с которой я столкнулся, заключается в том, что для чтения экземпляра String требуется, чтобы строка была в кавычках. Я не хочу вводить "Fred" в консоли, чтобы изменить имя, когда я действительно хочу набрать Fred.

Есть ли простой способ сделать это, чтобы requestValue полиморфный?

Ответы [ 2 ]

4 голосов
/ 15 мая 2011

Поскольку вы хотите добавить свое собственное пользовательское поведение read для имен пользователей, способ сделать это - написать новый экземпляр для чтения имен.Чтобы сделать это , мы можем создать новый тип для имен:

import Control.Arrow (first)

newtype Name = Name { unName :: String }
    deriving (Eq, Ord, Show)

и написать для него пользовательский read:

instance Read Name where
    readsPrec n = map (first Name) . readsPrec n . quote
        where quote s = '"' : s ++ ['"'] 

это то же самоев качестве экземпляра для чтения строк, но сначала мы цитируем строку, после чтения ее.

Теперь вы можете изменить тип Person, чтобы использовать Name вместо String:

data Person = Person { age :: Int
                     , name :: Name } deriving Show  

и мы находимся в бизнесе:

*Main> changeName (Person 31 (Name "dons"))
Please enter a new value for name
Don
Person {age = 31, name = Name {unName = "Don"}}
2 голосов
/ 15 мая 2011

Вы хотите getLine, а не readLn.

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