总结Haskell

时间:2016-05-16 16:28:25

标签: haskell recursion

我是Haskell的新手 - 以及函数式编程 - 我想知道如何在Haskell中编写这样的函数。我已经习惯了命令式语言,但是现在处理haskell中的递归对我来说是难以捉摸的。注意,我知道奇数的和可以用n ^ 2来完成(即3个第一奇数的总和1 + 3 + 5 = 9 = 3 ^ 2)但是想法是学习函数编程的递归。

另外,我这样做是代数研讨会的一部分,我们还没有看到。我需要一种方法来解决它只有递归。

任何提示?谢谢!

4 个答案:

答案 0 :(得分:9)

-- the odd numbers (all of them!)
[ 1,3.. ]

-- the first N odd numbers:
take n [1,3..]

-- the sum of the first N odd numbers
sum (take n [1,3..])

把它放在一个函数中:

sumOddNumbers n = sum (take n [1,3..])

答案 1 :(得分:5)

首先,您需要描述您的功能。

sumFirstOdds :: Int -> Int

当你考虑递归时,你需要一个停止点。在这种情况下,良好的停止点是第一个零奇数的总和,即零。您可以像这样定义基本情况:

sumFirstOdds 0 = 0

养成在你编写递归函数时首先声明停止点的习惯是很好的。否则你很容易就会遇到无限循环。

现在我们需要定义当我们想要在n时找到第一个n > 0奇数的总和时会发生什么。

您首先需要找到一种方法来获取第n个奇数的值:(n * 2) - 1

现在为递归部分。通过几个简单的例子,它可以帮助您思考问题。如果我们想得到前3个奇数的总和,我们将使用这样的公式:

((3 * 2) - 1) + ((2 * 2) - 1) + ((1 * 2) - 1) + 0
  ^               ^               ^             ^
  |               |               |             |
n == 3          n == 2          n == 1        n == 0 (base case)

从请求的3开始使用相同的算法,并将其添加到针对2运行的相同算法的结果中,然后对1执行相同的操作并再次执行0,这是我们查看基本情况的地方并停止。

输入Haskell代码,你可以把它写成:

sumFirstOdds n = ((n * 2) - 1) + (sumFirstOdds (n-1))

计算是针对当前n值执行的,并且该值将添加到针对该n-1值使用的相同函数的结果中。

重申最终功能的样子,就是这样:

sumFirstOdds :: Int -> Int
sumFirstOdds 0 = 0
sumFirstOdds n = ((n * 2) - 1) + (sumFirstOdds (n-1))

注意:这并不能很好地处理负输入但我为了简单起见而将其排除在外

答案 2 :(得分:2)

因为你应该总是通过平方来对奇数求和,我认为用递归来那个会很有趣。既然对var Dog = function(name){ this.name = name; } Dog.prototype.type = function(){ return this; } Dog.prototype.getName = function(){ //console.log(this.type()) return "Dog's name: " + this.type(); // <- Calls toString method } Dog.prototype.toString = function(){ return this.name; }; var spot = new Dog('spot'); console.log(spot.getName()); Int采用这种方式很愚蠢,那么您应该在类型级别工作。这实际上和总结天真的方式一样慢,但它更有趣!

Integer

现在,为了使这个可用,你可以用单身人士将它降低到术语水平。

{-# LANGUAGE DataKinds, KindSignatures, TypeFamilies, TypeOperators, GADTs, UndecidableInstances #-}

data Nat = Z | S Nat

infixr 6 :+
type family (:+) (x :: Nat) (y :: Nat) :: Nat where
  'Z :+ n = n
  'S m :+ n = 'S (m :+ n)

infixr 7 :*
type family (:*) (x :: Nat) (y :: Nat) :: Nat where
  'Z :* n = 'Z
  'S m :* n = n :+ m :* n

答案 3 :(得分:1)

这里不需要,但通常可以在辅助函数中使用累加器进行递归计算。

sumodds n = go n 0
   where go 0 a = a
         go k a = go (k-1) (a + 2*k-1)

> map sumodds [0..9]
[0,1,4,9,16,25,36,49,64,81]