String 如何在非双引号的字符串上使用read?

String 如何在非双引号的字符串上使用read?,string,parsing,haskell,io,String,Parsing,Haskell,Io,我正在使用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"

我正在使用
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'}
changeAge::Person->IO Person
变化p=do

age'由于您希望为用户名添加自己的自定义
读取
行为,因此方法是实际为用户名编写一个新实例。为此,我们可以为名称创建一个新类型:

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 ++ ['"'] 
这与字符串的read实例相同,但在中读取字符串后,我们首先引用该字符串

现在,您可以修改您的
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"}}

你想要的是
getLine
,而不是
readLn

不,我不想要。getLine的类型为
IO String
,而readLn的类型为
IO a
。我希望requestValue的类型为
String->IO a
,所以我需要的是readLn,而不是getLine。是的,请看Don的答案。:)您不也应该注意转义带引号的字符串吗?