Haskell 哈斯克尔:打印案例编号
我编写了一个Haskell代码,如下所示:Haskell 哈斯克尔:打印案例编号,haskell,Haskell,我编写了一个Haskell代码,如下所示: loop = do x <- getLine if x == "0" then return () else do arr <- replicateM (read x :: Int) getLine let blocks = map (read :: String -> Int) $ words $ unwords arr putStr "Case X : output = ";
loop = do
x <- getLine
if x == "0"
then return ()
else do arr <- replicateM (read x :: Int) getLine
let blocks = map (read :: String -> Int) $ words $ unwords arr
putStr "Case X : output = "; -- <- What should X be?
print $ solve $ blockPair blocks;
loop
main = loop
有人知道如何做到这一点吗?另外,如果可能的话,你能给我建议一种在最后打印输出行的方法吗
提前感谢。对于问题的第一部分,当前案例编号是您希望在程序执行过程中保持的某些“状态”的示例。在其他语言中,您无疑会使用可变变量 在Haskell中,有几种处理状态的方法。最简单的方法之一(尽管有时有点难看)是将状态显式地作为函数参数传递,考虑到您已经构建代码的方式,这将非常有效:
main = loop 1
loop n = do
...
putStr ("Case " ++ show n ++ ": Output = ...")
...
loop (n+1) -- update "state" for next loop
你问题的第二部分有点复杂。看起来你想要的是提示而不是解决方案。为了让您开始,让我向您展示一个函数的示例,该函数读取行,直到用户输入end
,然后返回到但不包括end
(以及一个main
函数,该函数主要使用纯代码对行执行一些有趣的操作):
对于问题的第一部分,当前案例编号是您希望在程序执行过程中保持的某个“状态”的示例。在其他语言中,您无疑会使用可变变量 在Haskell中,有几种处理状态的方法。最简单的方法之一(尽管有时有点难看)是将状态显式地作为函数参数传递,考虑到您已经构建代码的方式,这将非常有效:
main = loop 1
loop n = do
...
putStr ("Case " ++ show n ++ ": Output = ...")
...
loop (n+1) -- update "state" for next loop
你问题的第二部分有点复杂。看起来你想要的是提示而不是解决方案。为了让您开始,让我向您展示一个函数的示例,该函数读取行,直到用户输入end
,然后返回到但不包括end
(以及一个main
函数,该函数主要使用纯代码对行执行一些有趣的操作):
这在精神上类似于K.A.布尔的回答(关键的动作仍然是将状态作为一个参数传递),但考虑因素不同,以展示一个巧妙的技巧。由于
IO
操作只是正常的Haskell值,因此可以使用循环来构建操作,该操作将打印输出,而无需执行:
loop :: (Int, IO ()) -> IO ()
loop (nCase, prnAccum) = do
x <- getLine
if x == "0"
then prnAccum
else do inpLines <- replicateM (read x) getLine
let blocks = map read $ words $ unwords inpLines
prnAccumAndNext = do
prnAccum
putStr $ "Case " ++ show nCase ++ " : output = "
print $ solve $ blockPair blocks
loop (nCase + 1, prnAccumAndNext)
main = loop (1, return ())
loop::(Int,IO())->IO()
循环(nCase,prnAccum)=do
这在精神上与K.A.布尔的回答类似(关键的动作仍然是将状态作为一个参数传递),但为了展示一个巧妙的技巧,考虑因素不同。由于IO
操作只是正常的Haskell值,因此可以使用循环来构建操作,该操作将打印输出,而无需执行:
loop :: (Int, IO ()) -> IO ()
loop (nCase, prnAccum) = do
x <- getLine
if x == "0"
then prnAccum
else do inpLines <- replicateM (read x) getLine
let blocks = map read $ words $ unwords inpLines
prnAccumAndNext = do
prnAccum
putStr $ "Case " ++ show nCase ++ " : output = "
print $ solve $ blockPair blocks
loop (nCase + 1, prnAccumAndNext)
main = loop (1, return ())
loop::(Int,IO())->IO()
循环(nCase,prnAccum)=do
x“另外,如果可能的话,你能给我建议一种在最末端打印输出行的方法吗?”--我不确定你还想打印什么,应该在什么时候打印。@duplode,它应该在开始时像所有输入一样运行,然后在用户输入一个0后,它应该打印输出。我需要一些帮助。。。您知道您在read
上的类型签名是不必要的吗?你可以说,例如,`replicItem(read x)getLine。类型推断将确定您试图读取的类型。(我第一次这么做的时候感觉就像变魔术了)@luqui。谢谢你的提示。我只是Haskell的初学者。“另外,如果可能的话,你能给我建议一种在最后打印输出行的方法吗?”--我不确定你还想打印什么,应该在什么时候打印。@duplode,它应该像所有输入一样运行,然后在用户输入0之后,它应该打印输出。我需要一些帮助。。。您知道您在read
上的类型签名是不必要的吗?你可以说,例如,`replicItem(read x)getLine。类型推断将确定您试图读取的类型。(我第一次这么做的时候感觉就像变魔术了)@luqui。谢谢你的提示。我只是Haskell的初学者。谢谢,你的第一个技巧成功了。但是关于第二个,我有一个类似的函数,它在0输入端终止,但是如何控制传递到输出函数的参数呢?您的代码将把每一行作为单独的参数进行处理,这不是我想要的。无论如何,谢谢你的尝试。是的,现在你的方法更清晰了。这正是我想要的。我想问题现在已经解决了。非常感谢。@user7201762,如果这个答案成功了,您可以单击答案顶部的复选标记将其标记为“已接受答案”。谢谢,您的第一个技巧成功了。但是关于第二个,我有一个类似的函数,它在0输入端终止,但是如何控制传递到输出函数的参数呢?您的代码将把每一行作为单独的参数进行处理,这不是我想要的。无论如何,谢谢你的尝试。是的,现在你的方法更清晰了。这正是我想要的。我想问题现在已经解决了。非常感谢。@user7201762,如果这个答案成功了,您可以单击答案顶部的复选标记将其标记为“已接受答案”。
main = do
blocks <- readBlocks
putStr $ unlines $
zipWith (\n line -> "Case " ++ show n ++ ": " ++ line)
[1..] (map (show . solve . blockPair) blocks)
loop :: (Int, IO ()) -> IO ()
loop (nCase, prnAccum) = do
x <- getLine
if x == "0"
then prnAccum
else do inpLines <- replicateM (read x) getLine
let blocks = map read $ words $ unwords inpLines
prnAccumAndNext = do
prnAccum
putStr $ "Case " ++ show nCase ++ " : output = "
print $ solve $ blockPair blocks
loop (nCase + 1, prnAccumAndNext)
main = loop (1, return ())