haskell - 如何在 Haskell 递归调用中打印迭代?

标签 haskell recursion

考虑下面的代码,它返回一个数字的阶乘:

factorial n = go n 1
  where
    go n ret | n > 1 = go (n-1) (ret * n)
             | otherwise = ret
如何打印 ngo n ret 的每个递归调用中?由于n每次都在递减,我想看看是否可以在每次递减时打印它(如 5 4 3 2 1 )。
这就是我尝试这样做的方式(这是完全错误的),但我想不出不同的方式:
factorial n = go n 1
  where
    go n ret | n > 1 = go (n-1) (ret * n) print n
             | otherwise = ret

最佳答案

方式
要打印,您需要将值提升到 I/O 应用程序;类型将从

factorial :: (Num a, Ord a) => a -> a
factorial :: (Num a, Ord a, Show a) => a -> IO a
什么go行动确实go action需要做两件事:
  • 打印号码n
  • 要么递归调用go或产生结果

  • 如何顺序执行两个 I/O 操作
    为了做两件事,我们需要一些组合器来组合它们。这里合适的是 *> :

    (*>) :: Applicative f => f a -> f b -> f b

    Sequence actions, discarding the value of the first argument.


    这正是我们所需要的,因为我们不需要使用第一个 Action 的值( print Action 的类型是 IO (),因此它不包含任何有用的结果)。
    将值提升到 I/O
    我们还需要 pure 在末尾

    pure :: Applicative f => a -> f a

    Lift a value.


    将结果提升到 I/O 应用程序中。
    编码
    factorial n = go n 1
      where
        go n acc =
          print n *>
          if n > 1
            then let !acc' = acc * n
                 in  go (n-1) acc'
            else pure acc
    
    !acc' 的绑定(bind)中forces立即发生乘法(感谢 Daniel Wagner 指出需要这样做)。
    在 GHCi 中进行测试:
    λ> factorial 5 >>= print
    5
    4
    3
    2
    1
    120
    

    关于haskell - 如何在 Haskell 递归调用中打印迭代?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48845646/

    相关文章:

    Javascript嵌套数组获取元素

    haskell - 为什么 GHC 提示非详尽的模式?

    haskell - 如何在 hackage 包中搜索功能?

    algorithm - DPLL算法和访问节点数

    powershell - 如何使用PowerShell递归删除具有特定名称的文件夹?

    java - 为什么在java中递归实现合并排序时会出现Stackoverflow异常?

    algorithm - 斐波那契数列递归空间复杂度

    list - 如何将返回 [] 的函数转换为 Traversable?

    mongodb - 在 Haskell 中授权连接到 mongoDB

    algorithm - 是否可以开发一种递归自动换行算法?