gpt4 book ai didi

haskell - Haskell IO 多行读取技术

转载 作者:行者123 更新时间:2023-12-01 19:15:46 25 4
gpt4 key购买 nike

基本上我想找到一种方法,以便用户可以输入测试用例的数量,然后输入他们的测试用例。然后程序可以运行这些测试用例并按照测试用例出现的顺序打印结果。

所以基本上我有 main 来读取测试用例的数量并将其输入到一个将从 IO 读取多次的函数中。它看起来像这样:

main = getLine >>= \tst -> w (read :: String -> Int) tst [[]]

这是w的方法签名:w::Int -> [[Int]]-> IO ()

所以我的计划是读取测试用例的数量,并让 w 运行一个函数,该函数接受每个测试用例并将结果存储到 [[]] 变量中。所以列表中的每个列表都将是一个输出。 w 将递归运行直到达到 0 并在单独的行上打印出每个列表。我想知道是否有更好的方法来做到这一点,因为我必须将一个空列表传递给 w,这似乎是无关的。

最佳答案

正如 @bheklilr 提到的,您无法更新像 [[]] 这样的值。标准函数方法是通过一组递归调用传递累加器。在以下示例中,loop 函数的 acc 参数就是此累加器 - 它由迄今为止收集的所有输出组成。在循环结束时我们返回它。

myTest :: Int -> [String]
myTest n = [ "output line " ++ show k ++ " for n = " ++ show n | k <- [1..n] ]

main = do
putStr "Enter number of test cases: "
ntests <- fmap read getLine :: IO Int
let loop k acc | k > ntests = return $ reverse acc
loop k acc = do
-- we're on the kth-iteration
putStr $ "Enter parameter for test case " ++ show k ++ ": "
a <- fmap read getLine :: IO Int
let output = myTest a -- run the test
loop (k+1) (output:acc)
allOutput <- loop 1 []
print allOutput

当你对这种模式越来越熟悉时,你会发现它是一个折叠(实际上是一个单子(monad)折叠,因为我们正在做 IO),并且你可以使用 foldM 来实现它.

更新:为了帮助解释 fmap 的工作原理,以下是不使用 fmap 编写的等效表达式:

With fmap:                                 Without fmap:

n <- fmap read getLine :: IO [Int] line <- getLine
let n = read line :: Int

vals <- fmap (map read . words) getLine line <- getLine
:: IO [Int] let vals = (map read . words) line :: [Int]

使用fmap可以让我们消除中间变量line,无论如何我们都不会再引用它。我们仍然需要提供类型签名,以便 read 知道要做什么。

关于haskell - Haskell IO 多行读取技术,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27847521/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com