Haskell中的递归算术序列

Bri*_*son 3 haskell

自从我学习代数课以来已有将近30年的时间,我正在努力学习 Haskell中的一些概念,因为我正在学习一门Haskell.我现在正在研究的概念是"递归".我已经观看了几个关于这个主题的youtube视频,发现了一个有算术序列问题的网站:一个n = 8 + 3(一个n-1)我理解为n = a n-1 + 3这就是我所拥有的在哈斯克尔.

addThree :: (Integral a) => a -> a
addThree 1 = 8
addThree n = (n-1) + 3
Run Code Online (Sandbox Code Playgroud)

运行脚本会产生:

addThree 1
8
addThree 2
4
addThree 3
6
Run Code Online (Sandbox Code Playgroud)

我能够在纸上解决这个和类似的递归,(在抛光很多锈之后),但是不理解Haskell中的语法.

我的问题如何根据我的例子在Haskell中定义基数和函数?


如果这不是这些问题的地方,请将我指向我应该发布的地方.我看到有超级用户,程序员和数学的堆栈交换,但不确定哪个Stack系列最适合我的问题.

Car*_*ten 8

首先一个代数和你的问题:我想你是稍微错了-如果我们写的3倍,这通常意味着3*X(Mathematicans甚至更懒然后程序员),所以您的系列确实应该看起来像一个ñ = 8 + 3*一n-1 IMO

然后一个n是一系列a中的第n个元素:a 0,a 1,a 2,a 3,...这就是为什么你们之间存在很大的差异(n-1),addThree (n-1)因为最后一个会指定一个n-1而第一个只是一个与你的系列没有真正联系的数字.


好吧,让我们来看看你的系列a n = 8 + 3a n-1(这就是我理解它的方式 - 因为否则你会得到x = 8 + 3*x因此只有x = -4:

  • 你可以选择0 - 让我们说它是0(就像你做的那样?)
  • 那么1 = 8 + 3*0 = 8
  • a 2 = 8 + 3*8 = 4*8 = 32
  • a 3 = 8 + 3*32 = 8 + 3*32 = 104
  • ...

好吧,假设你想使用递归而不是直接转换为Haskell的问题:

a :: Integer -> Integer
a 0 = 0
a n = 8 + 3 * a (n-1)

series :: [Integer]
series = map a [0..]
Run Code Online (Sandbox Code Playgroud)

给你(前5个元素):

?> take 5 series
[0,8,32,104,320]
Run Code Online (Sandbox Code Playgroud)

请注意,这是一种非常糟糕的执行方式 - 因为递归调用a确实会一遍又一遍地执行相同的工作.

解决此问题的技术方法是观察您只需要前一个元素来获取下一个元素并使用Data.List.unfoldr:

series :: [Integer]
series = unfoldr (\ prev -> Just (prev, 8 + 3 * prev)) 0
Run Code Online (Sandbox Code Playgroud)

现在当然你可以用Haskell获得更多的爱好者 - 例如你可以按原样定义系列(使用Haskells懒惰):

series :: [Integer]
series = 0 : map (\ prev -> 8 + 3 * prev) series
Run Code Online (Sandbox Code Playgroud)

而且我相信还有很多方法可以做到,但我希望这会对你有所帮助

  • @BrianWilson` <sub>下标</ sup>`. (2认同)
  • 对于下标,你只需要在文本编辑器中使用`a <sub> n-1 </ sub>` (2认同)