Haskell IO的多行读取技术
基本上,我想找到一种方法,让用户可以输入测试用例的数量,然后输入他们的测试用例。然后,程序可以运行这些测试用例,并按照测试用例出现的顺序打印结果 所以基本上我有main,它读取测试用例的数量,并将它输入到一个函数中,这个函数将从IO读取很多次。看起来是这样的:Haskell IO的多行读取技术,haskell,io,Haskell,Io,基本上,我想找到一种方法,让用户可以输入测试用例的数量,然后输入他们的测试用例。然后,程序可以运行这些测试用例,并按照测试用例出现的顺序打印结果 所以基本上我有main,它读取测试用例的数量,并将它输入到一个函数中,这个函数将从IO读取很多次。看起来是这样的: main = getLine >>= \tst -> w (read :: String -> Int) tst [[]] 这是w:w::Int->[[Int]]->IO() 因此,我的计划是读取测试用例的数量,
main = getLine >>= \tst -> w (read :: String -> Int) tst [[]]
这是w:w::Int->[[Int]]->IO()
因此,我的计划是读取测试用例的数量,让w运行一个函数,该函数接收每个测试用例,并将结果存储到[[]]变量中。因此,列表中的每个列表都将是一个输出。w将递归运行,直到它达到0,并在单独的一行上打印每个列表。我想知道是否有更好的方法来实现这一点,因为我必须将一个空列表传递到w,这似乎是无关的。正如@bheklillr提到的,您不能更新像
[[]]
这样的值。标准的函数方法是通过一组递归调用传递累加器。在下面的示例中,循环
函数的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
使用
fmap
可以消除中间变量line
,我们无论如何都不会再引用它。我们仍然需要提供类型签名,以便read
知道该做什么。惯用的方法是使用replicitem
:
runAllTests :: [[Int]] -> IO ()
runAllTests = {- ... -}
main = do
numTests <- readLn
tests <- replicateM numTests readLn
runAllTests tests
-- or:
-- main = readLn >>= flip replicateM readLn >>= runAllTests
runAllTests::[[Int]]->IO()
runAllTests={-…-}
main=do
numTests=flip replictem readLn>>=runAllTests
将结果存储在[[]]
变量中是什么意思<代码>[[]]不是一个变量,它是一个不可变的值,就像所有其他Haskell值一样。如果要读取特定数量的行,可以使用Control.Monad.replicItem n getLine
,其中n
是要读取的行数。因此,我会继续将结果附加到列表列表中,并在最后打印出所有结果。我不知所措,因为我无法同时返回列表列表和使用IO()类型。我是否应该执行类似于fmap read$words getLine::[IO Int]
?谢谢。关于:IO[Int]
部分的问题。我如何解释它?是不是说fmap会返回IO[Int]信息?然后我们使用正确的。我已经更新了答案来帮助解释fmap是如何工作的。非常感谢。如果可以的话,还有一个问题,(map read.words)
要映射到getLine的函数是什么?我将如何解释地图阅读。单词
?它是否需要一些[Char]输入,然后将其更改为[[Char]],并在其上进行读取映射?
runAllTests :: [[Int]] -> IO ()
runAllTests = {- ... -}
main = do
numTests <- readLn
tests <- replicateM numTests readLn
runAllTests tests
-- or:
-- main = readLn >>= flip replicateM readLn >>= runAllTests