简单的Haskell循环

52

我刚开始学习 Haskell,但目前缺少循环机制让我感到无限沮丧。我已经学会如何为函数编写循环,但我的问题是在迭代循环过程中想要输出一些结果。似乎我必须使用调试来执行这个简单的任务。

因此,现在我只想要一个在主结构中打印字符串10次的例子。

换句话说,我想要做这件事情10次:

main = do  
    putStrLn "a string" 

谢谢。我觉得这会对我的任务非常有启发。


3
在函数式编程语言中,当你想要执行“循环”时,你需要使用递归来解决实际问题。唯一的麻烦之处是,如果你仔细看,类型无法匹配,因为有单子(在这种情况下是IO)构造器的存在。因此,你需要一个递归结构,把单子绑定一直嵌入到底部。换句话说,这只是递归,稍微变化了一下以处理Haskell处理IO的“特殊”方式。 - Kristopher Micinski
虽然我是Haskell的初学者,但我想分享一下我所获得的一点见解。有人告诉我,在Haskell中想要进行循环操作时,可以考虑使用递归或列表推导式。虽然这与你在这里提出的问题无关,但假设你想要将列表中的所有元素相加。当然,你需要遍历所有元素。递归可以实现,使用列表推导式也可以。 - John Red
@JohnRed 我认为你不能使用LC来对列表进行求和。LC基本上只是flatMap - Will Ness
6个回答

71
您可以定义一个递归函数,该函数打印"a string" n次(n是函数的参数),如下所示:
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_


46

当你刚开始学习Haskell的IO时,它可能有些棘手,因为它基于单子。

然而,你的问题有一个简单的解决方案:

main = replicateM_ 10 $ putStrLn "a string"

这里使用了来自Control.Monad的组合子replicateM_

它有许多有用的函数,可用于组合和执行单子动作。


16
为了让他更好地理解你的回答:Haskell有forwhile循环,但它们是库函数而不是语言内置函数。例如,相当于for循环的是来自Control.MonadforM_组合器。然而,在这种情况下,replicateM_更加简洁。 - Gabriella Gonzalez

4

我也是Haskell的初学者,我有一个解决方案,虽然不够优雅,但在实际使用中很有用。

main = do 
    putStr result
    where
        string = "a string"
        result = concat [string ++ "\n" | i <- [1,2..10]]

因此,在这里我们定义了一个列表,其中的元素是您要打印的字符串,后跟换行字符。


2

我认为最紧迫的for循环形式是:

for list action = mapM_ action list

main :: IO Int
main = do
    for [0..10] (\ i -> do

        print(i^2)
        )
    return 0

这实际上看起来非常像 C 代码。


1

我的解决方案:

n = 10
doSomething () = putStrLn "a string"
main = sequence (replicate n (doSomething()))
  • sequence: 顺序解决列表中的每个IO a
  • replicate n ele: 构建一个重复ele n次的列表,类似于take n (repeat ele)

1

这样做可以使特定函数循环,使其更具可重用性(而不是为每个要循环的新事物编写它)。

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 ""
  )

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接