Haskell - 读取人员列表

Geo*_*nat 5 io haskell

问题听起来是这样的:编写一个程序,读取数字 n,然后读取 n 个人,对于每个人,读取他们的姓名和年龄,然后返回最年长的人/人。

输入示例:

3
Ion Ionel Ionescu
70
Gica Petrescu
99
Mustafa ben Muhamad
7
Run Code Online (Sandbox Code Playgroud)

输出示例

Oldest is Gica Petrescu (99 years).
Run Code Online (Sandbox Code Playgroud)

到目前为止我的代码:

readPers :: IO(String, Int)
readPers = do
    name <- getLine
    age <- readLn :: IO Int
    return (name, age)

readPerss :: (Ord t, Num t) => t -> [IO (String, Int)]
readPerss n
    | n > 0 = readPers : readPerss(n-1)
    | otherwise = []

pFunc = do
    print "Numer of persons:"
    n <- readLn :: IO Int
    let persons = readPerss n
    return persons
Run Code Online (Sandbox Code Playgroud)

我首先阅读 n,然后尝试使用 readPers 和 readPerss 制作一个人员列表,但我陷入困境,我不知道如何从那时起解决它,我猜到目前为止我的实现不太正确。

我该如何解决这个问题?

Jon*_*rdy 3

你们非常接近!您正在做的readPerss :: (Ord t, Num t) => t -> [IO (String, Int)]是返回一个操作列表IO;每个动作执行时都会返回一对Stringand 。Int目前,pFunc您仅构建此操作列表,将其存储在变量中let,并从 ; 返回它pFunc;您永远不会使用 \xe2\x80\x9cbind\xe2\x80\x9d 语句执行它们<-

\n\n

有一些简单的方法可以做你想做的事。执行您想要的操作的代码的最小更改是 add sequence,它采用一个操作容器并生成一个返回容器的操作

\n\n
sequence :: (Traversable t, Monad m) => t (m a) -> m (t a)\n
Run Code Online (Sandbox Code Playgroud)\n\n

t[]mIOa(String, Int)

\n\n
sequence :: [IO (String, Int)] -> IO [(String, Int)]\n
Run Code Online (Sandbox Code Playgroud)\n\n

另一种方法是重写,readPerss以便直接执行操作,将(String, Int) 结果累积在列表中,而不是累积IO 操作

\n\n
readPerss :: (Ord t, Num t) => t -> IO [(String, Int)]\n-- Change [IO \xe2\x80\xa6] to IO [\xe2\x80\xa6]:         ~~~~~~~~~~~~~~~~~~\n\nreadPerss n\n  | n > 0 = do\n    pers <- readPers\n    perss <- readPerss (n - 1)\n    return (pers : perss)\n  | otherwise = return []\n
Run Code Online (Sandbox Code Playgroud)\n\n

我知道如果这是作业或练习,您可能不应该使用库函数,但在典型的代码中 \xe2\x80\x9creat 重复x操作n次数并累积结果\xe2\x80\x9d 通常表示为replicateM n x

\n\n
replicateM :: Applicative m => Int -> m a -> m [a]\n
Run Code Online (Sandbox Code Playgroud)\n