2017-09-09 38 views
4

我正在通过了解您对Haskell的好感并试图通过递归的一章中的一些示例问题。如何使用两个参数设置递归函数的初始条件(Haskell)

我试图写一个函数,它带有一个下界“a”和一个上界“b”,并返回包含在内的所有数字的和。

我最初试图(我认为是)一个直接的方法

sumInts :: Int -> Int -> Int 
sumInts a a = a 
sumInts a b = (sumInts (a) (b-1)) + b 

当我试图编译,我得到一个错误的语句

•为 'A'

冲突的定义

我最终只是想让事情发挥作用,所以我把应该是一个功能的东西分成两部分。

sumInts' :: Int -> Int 
sumInts' 0 = 0 
sumInts' a = sumInts' (a-1) + a 


sumInts :: Int -> Int -> Int 
sumInts 0 b = sumInts' b 
sumInts a b = (sumInts (a-1) (b)) - (a-1) 

我试过寻找你认为会是一个非常简单的问题。唉,看起来结果太有利可图。

我该如何将两个函数结合成一个函数?另外,为什么我的原始功能没有工作?有关如何在将来避免这种情况的任何提示?谢谢!

+3

也不错的经验法则是不要传递在递归中永远不会改变的参数。相反,使用'where'子句并引用常数值越高:'sumInts lo = go where go hi = if hi <= lo then hi hi + go(hi-1)'。 – jberryman

回答

3

模式匹配是线性。这意味着在函数的头部(模式匹配部分)中不能写入两次变量。所以你的条款:

sumInts a a = a 

是不允许的。在这种情况下,你可以使用守卫

sumInts :: (Num a, Ord a) => a -> a -> a 
sumInts a b | a <= b = a + sumInts (a+1) b 
      | otherwise = 0

的警卫管道字符(|)之后的条件。在满足条件的情况下,该功能评估为等号右侧的部分(=)。 otherwise只是True的别名。

0

我知道问题是关于递归,但最简单的方法只使用一个函数是根本不使用递归,而是一个简单的数学公式。在Haskell

sumInts :: Int -> Int -> Int 
sumInts a b = ((a + b)/2) * (b - a + 1) 
+0

我认为这个公式不正确。 'sumInts 5 6'应该是'11',但是这个函数返回'0'。 – 4castle

+0

在这个公式中,'b'应该是较小的数字,而不是较大的数字。 – amalloy

+0

@amalloy是的,的确如此。我编辑它以反映原始功能。 – Kapol