Haskell中的求和 - 功能编程

时间:2017-10-17 19:57:14

标签: haskell recursion functional-programming

我在Haskell中编写一个简单的函数时遇到了麻烦...这是为了计算从1到n的数字之和。我不允许使用if语句,因为我的老师希望我们专注于功能编程。任何帮助,将不胜感激。谢谢!

summation :: Integer -> Integer
summation n
  | n > 1 = n + summation(n-1)
  | n == 1 = 1

这是GHCi的输出:

clase4.hs:13:28: error:
    Variable not in scope: (?) :: Integer -> Integer -> Integer
Failed, modules loaded: none.

第13行是:

     | n > 1 = n + summation(n-1)

我已经评论了文件中的其他内容,但我仍然遇到了这个错误。我看不到'?'任何地方。这些是屏幕截图:

File

GHCi output

2 个答案:

答案 0 :(得分:10)

在源文件clase4.hs中,认为的字符是表达式n-1中的标准ASCII减号。相反,你可能已经使用了一些其他的unicode字符,比如“en dash”或只有看起来的东西就像一个减号(也许是因为你在像Microsoft Word这样奇怪的东西中编辑了文件)复制并粘贴了一些搞乱角色的来源代码。

Haskell将无效字符打印为“?”因为,据它所知,你的输出终端不支持显示坏字符所需的编码。 (这是在Windows环境中运行Haskell时的常见问题,但如果事情设置奇怪,可能会在其他平台上发生。)

使用正确的文本编辑器打开源文件,突出显示“减号”并在键盘上重新键入。在西班牙语键盘上,这应该是右下移键的左侧键;在美国键盘上,它位于零键的右侧。

如果失败,请尝试将您自己的程序从Stack Overflow复制并粘贴到一个全新的文本文件中并编译 - 从您的问题中复制和粘贴对我们其他人来说正常。

答案 1 :(得分:1)

在我看来,这里存在两个问题:

  1. 您的递归通话调用sumatoria,而您的功能是summation;
  2. 您检查的n > 1n == 1是否相当不安全。
  3. 我们可以通过sumatoria替换summation来解决问题,并使警卫更安全:

    summation :: Integer -> Integer
    summation n
      | n >= 1 = n + summation (n-1)
      | otherwise = 0

    现在它应该工作了。我们使用otherwise = 0,以便输入0或负数时,我们会获得0

    尽管如此,我们仍然可以改进这项功能。首先,我们不应仅限于Integer s。我们可以使用任何Numa Ordsummation :: (Num a, Ord a) => a -> a summation n | n > 1 = n + summation (n-1) | otherwise = 0。所以我们可以将其重写为:

    1..n

    此外,0..nsummation :: Integral a => a -> a summation n = div (n * (n+1)) 2 的总和可以使用以下公式计算:

    n
    ---
    \         n * (n+1)
    /    i  = ---------
    ---           2
    i=1

    所以我们可以把它写成:

    div :: Integral a => a -> a -> a

    a要求Integralsum。如果乘法,增量和除法都是 O(1)运算,那么现在就是 O(1)函数。

    最后请注意,除了使用递归之外,您还可以使用summation :: (Enum a, Num a) => a -> a summation n = sum [1..n] 之类的函数。在这种情况下,您可以使用:

    Sub clean_and_graph()
    
    'start with the first sheet
    Application.ScreenUpdating = False
    For Each sh In Worksheets
       sh.Activate
    
    
    'find the collength for the series entry
        Dim collength As Integer
        collength = Cells(Rows.Count, "A").End(xlUp).Row
    'clean up the data
        'Inserting a Column at Column C
            Range("C1").EntireColumn.Insert
            [C1].Value = "time"
    
            'eqn for first row in column
            [C2].Value = "=if(B2>0,24*(B2-$B$2))"
            'autofill rest of columns and format data to general
            Range("C2:C" & collength).FillDown
            Columns(3).NumberFormat = "General"
    
        'create the chart as an object in the worksheet
        Dim myChtObj As ChartObject
        Set myChtObj = ActiveSheet.ChartObjects.Add _
            (Left:=100, Width:=375, Top:=75, Height:=225)
        myChtObj.Chart.SetSourceData Source:=Sheets(ActiveSheet.Name).Range("C2:Q" & collength)
        myChtObj.Chart.ChartType = xlXYScatterLines
    
    
        With myChtObj.Chart
    
            ' make an XY chart
            .ChartType = xlXYScatterLines
    
            ' remove extra series
            Do Until .SeriesCollection.Count = 0
                .SeriesCollection(1).Delete
            Loop
             With .SeriesCollection.NewSeries
            .Name = ActiveSheet.Range("Q1")
            .Values = ActiveSheet.Range("Q2:Q" & collength)
            .XValues = ActiveSheet.Range("C2:C" & collength)
            End With
        End With
    
    
    'go to the next sheet
        Next sh
    Application.ScreenUpdating = True
    
    End Sub