【问题标题】:simple Haskell loop简单的 Haskell 循环
【发布时间】:2013-04-14 21:11:02
【问题描述】:

我刚开始学习 Haskell,但是现在没有循环是非常令人沮丧的。我想出了如何为函数编写循环。但是,我的问题是我想在迭代循环时输出一些结果。看来我必须使用调试来执行这个简单的任务。

所以现在我只需要一个示例,说明如何在主结构中打印 10 次字符串。

也就是说,我想这样做 10 次:

main = do  
    putStrLn "a string" 

谢谢。我觉得这对我的任务很有启发性。

【问题讨论】:

  • 这里要回答的真正问题是,当您想在函数式语言中执行“循环”时,您会使用递归。唯一令人讨厌的是,如果您查看它:类型不对齐,因为 monad 构造函数(在本例中为 IO)。因此,您需要一个递归结构来“拼接”单子绑定。换句话说,这只是递归,处理 Haskell 处理 IO 的“特殊”方式略有不同。
  • 即使我是 Haskell 的初学者,但我想分享一下我所获得的一些见解。有人告诉我,当你想在 Haskell 中做循环时,可以考虑递归或列表推导。此处与您的问题无关,但假设您要在列表中添加所有元素。当然,您需要遍历所有元素。递归将起作用,使用列表推导也是如此。
  • @JohnRed 我不认为你可以用 LC 总结一个列表。 LC 基本上就是flatMap

标签: loops haskell io


【解决方案1】:

您可以定义一个递归函数,将“字符串”打印 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_

【讨论】:

    【解决方案2】:

    Haskell 的 IO 在您刚开始时有点棘手,因为它基于 monad。

    虽然您的问题有一个简单的解决方案:

    main = replicateM_ 10 $ putStrLn "a string"
    

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

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

    【讨论】:

    • 为了他的利益详细说明您的答案:Haskell 有 forwhile 循环,但它们是库函数而不是语言内置函数。例如,for 循环的等价物是来自Control.MonadforM_ 组合子。不过,在这种情况下,replicateM_ 更简洁。
    【解决方案3】:

    我也是 Haskell 的初学者,我有一个不太优雅但实用的解决方案。

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

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

    【讨论】:

      【解决方案4】:

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

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

      【讨论】:

        【解决方案5】:

        我认为执行 for 循环的最必要的形式是:

        for list action = mapM_ action list
        
        main :: IO Int
        main = do
            for [0..10] (\ i -> do
        
                print(i^2)
                )
            return 0
        

        在我看来,这实际上很像 C 代码。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-05-14
          • 2017-05-22
          • 1970-01-01
          • 2011-08-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多