【问题标题】:Using Recursion and Accumulators in Haskell在 Haskell 中使用递归和累加器
【发布时间】:2021-07-06 11:28:27
【问题描述】:

我正在尝试使用保护递归,但我在使用 Haskell 语法时遇到了困难。
我正在尝试在 Haskell 中使用递归来减少整数“n”次,直到达到我想要的基本情况,同时跟踪“n”,然后返回减少的整数和“n”作为我的一条信息的元组。

我的基本情况是整数在 1 到 13 之间。

例如,

Prelude> reduce 42
(3, 2)

Prelude> reduce 3
(3, 0)

为了解释逻辑,

Prelude> reduce 42
( (((42 - 13) - 13) - 13), 1+1+1+1 ) --> assume the accumulator = 0, hence 0,1,2.
(3, 3)

Prelude> reduce 3
(3, 0) --> already in base case!

目前,我有

reduce (x, 0)
  | x `elem` [1 .. 13] = (x, acc)
  | otherwise = reduce (x -13, acc + 1)
  where
    acc = 0

当然,我的 IDE 大喊我错了。我不知道如何在这个递归中实现初始化元组,这样它就像reduce :: a -> (a, b)
编辑:我想我越来越近了......但当然,我正在尝试将其实现为 a -> (a,b)

【问题讨论】:

    标签: haskell recursion accumulator


    【解决方案1】:

    如果您使用seq 正确管理惰性,使用累加器参数是一种很好的方法,而且确实是最有效的方法。然而,一种可以说更简单、可能更容易学习的技术将不使用累加器参数。相反,进行递归调用,然后修改其结果:

    reduce x | x `elem` [1..13] = (x, 0)
             | otherwise = let (y, n) = reduce (x - 13)
                           in (y, n + 1)
    

    进一步证明,“修改元组的第二个元素”有一个可爱的快捷方式 - 我不建议在您的第一个程序中使用它,但它是对可能发生的事情的有趣尝试:

    reduce x | x `elem` [1..13] = (x, 0)
             | otherwise = succ <$> reduce (x - 13)
    

    【讨论】:

      【解决方案2】:

      您需要使用辅助函数对其进行初始化:

      reduce::Int->(Int,Int)
      reduce x = reduce' (x,0)
      
      reduce'::(Int,Int)->(Int,Int)
      reduce' (x,n)
      
        | elem x [1..13] = (x,n) 
      
        | otherwise = reduce' (x-13,n+1)
      

      【讨论】:

      • 谢谢!我已经在教程中看到初始化变量时在函数名称末尾多次应用撇号(')的特定语法。你能解释一下reduce和reduce之间的区别吗?是否必须使用撇号?
      • @lattejiu:Haskell 变量/函数名称中的撇号意味着看起来像数学符号中的“质数”。当您不想提出不同的名称时,它被用作相关事物对的命名约定。这里reduce' 只是reduce 的“帮手”。有时,素数表示“严格”(例如foldl' / foldlmodifyIORef' / modifyIORef)。有时它意味着“更新”(例如x' = x + 1),尽管最好限制它,所以你最终不会试图区分x'''''x''''''之间的区别。您也可以在常规名称中使用它,例如don't.
      【解决方案3】:

      此位置不允许下划线。

      reduce::Int->Int                                                                                                                                                                        
       reduce x
          | elem x [1..13] = x
          | otherwise = reduce (x - 13)
       
      

      【讨论】:

        猜你喜欢
        • 2012-05-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-06-30
        • 1970-01-01
        • 1970-01-01
        • 2013-12-25
        相关资源
        最近更新 更多