自从我参加代数课以来已经将近30年了,我正在努力解决Haskell中的一些概念,因为我正在研究Learn you a Haskell。我现在正在研究的概念是"递归"。我已经观看了几个关于这个主题的youtube视频,发现了一个有算术序列问题的网站: n = 8 + 3(一个 n-1 ),据我所知a n = a n-1 + 3这就是我在Haskell中所拥有的。
addThree :: (Integral a) => a -> a
addThree 1 = 8
addThree n = (n-1) + 3
运行脚本会产生:
addThree 1
8
addThree 2
4
addThree 3
6
我能够在纸上解决这个和类似的递归,(在抛光很多锈之后),但是不理解Haskell中的语法。
我的问题如何根据我的示例在Haskell中定义基础和函数?
如果这不是这些问题的地方,请指导我到哪里发帖。我看到有超级用户,程序员和数学的堆栈交换,但不确定哪个Stack系列最适合我的问题。
答案 0 :(得分:8)
首先是代数上的单词而你有问题:我认为你有点错误 - 如果我们写3x它通常意味着3 * x(数学家甚至比程序员更懒)所以你的系列确实应该看起来像 n = 8 + 3 * a n-1 IMO
然后 n 是一系列a中的 n-元素:a 0 , 1 , 2 , 3 ,...这就是为什么(n-1)
和{{之间存在很大差异的原因1}}因为最后一个会指定一个 n-1 ,而第一个就是一个没有真正连接到你的系列的数字。
好的,让我们来看看你的系列a n = 8 + 3a n-1 (这是我理解它的方式 - 因为否则你会得到x = 8 + 3 * x,因此只有x = -4:
好吧,让我们说你想使用递归而不是直接转换成Haskell的问题:
addThree (n-1)
给你(前5个元素):
a :: Integer -> Integer
a 0 = 0
a n = 8 + 3 * a (n-1)
series :: [Integer]
series = map a [0..]
请注意,这是一种表现非常糟糕的方式 - 因为λ> take 5 series
[0,8,32,104,320]
中的递归调用反复执行同样的工作。
解决此问题的技术方法是观察您只需要前一个元素来获取下一个元素并使用a
:
Data.List.unfoldr
现在当然你可以使用Haskell获得更多的爱好者 - 例如你可以按原样定义系列(使用Haskells懒惰):
series :: [Integer]
series = unfoldr (\ prev -> Just (prev, 8 + 3 * prev)) 0
我相信还有很多方法可以做到这一点,但我希望这会对你有所帮助