我刚开始学习 Haskell,但目前缺少循环机制让我感到无限沮丧。我已经学会如何为函数编写循环,但我的问题是在迭代循环过程中想要输出一些结果。似乎我必须使用调试来执行这个简单的任务。
因此,现在我只想要一个在主结构中打印字符串10次的例子。
换句话说,我想要做这件事情10次:
main = do
putStrLn "a string"
谢谢。我觉得这会对我的任务非常有启发。
printStringNTimes 0 = return ()
printStringNTimes n =
do
putStrLn "a string"
printStringNTimes (n-1)
main = printStringNTimes 10
一个更为通用的方法是定义一个函数,它可以将任何IO操作重复执行n次:
repeatNTimes 0 _ = return ()
repeatNTimes n action =
do
action
repeatNTimes (n-1) action
main = repeatNTimes 10 (putStrLn "a string")
上述函数已经存在于Control.Monad
中,名称为replicateM_
。
当你刚开始学习Haskell的IO时,它可能有些棘手,因为它基于单子。
然而,你的问题有一个简单的解决方案:
main = replicateM_ 10 $ putStrLn "a string"
这里使用了来自Control.Monad
的组合子replicateM_
它有许多有用的函数,可用于组合和执行单子动作。
for
和while
循环,但它们是库函数而不是语言内置函数。例如,相当于for
循环的是来自Control.Monad
的forM_
组合器。然而,在这种情况下,replicateM_
更加简洁。 - Gabriella Gonzalez我也是Haskell的初学者,我有一个解决方案,虽然不够优雅,但在实际使用中很有用。
main = do
putStr result
where
string = "a string"
result = concat [string ++ "\n" | i <- [1,2..10]]
因此,在这里我们定义了一个列表,其中的元素是您要打印的字符串,后跟换行字符。
我认为最紧迫的for循环形式是:
for list action = mapM_ action list
main :: IO Int
main = do
for [0..10] (\ i -> do
print(i^2)
)
return 0
这实际上看起来非常像 C 代码。
我的解决方案:
n = 10
doSomething () = putStrLn "a string"
main = sequence (replicate n (doSomething()))
sequence
: 顺序解决列表中的每个IO a
replicate n ele
: 构建一个重复ele
n
次的列表,类似于take n (repeat ele)
这样做可以使特定函数循环,使其更具可重用性(而不是为每个要循环的新事物编写它)。
loop :: Int -> (IO()) -> IO()
loop 0 _ = return ()
loop n f =
do
f
loop (n - 1) f
例子:
main = do
loop 5 (do
putStr "hello "
putStrLn "there")
main = do
loop 3 (do
loop 4 (putStrLn "Hi")
putStrLn ""
)
flatMap
。 - Will Ness