我在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)
我已经评论了文件中的其他内容,但我仍然遇到了这个错误。我看不到'?'任何地方。这些是屏幕截图:
答案 0 :(得分:10)
在源文件clase4.hs
中,认为的字符是表达式n-1
中的标准ASCII减号。相反,你可能已经使用了一些其他的unicode字符,比如“en dash”或只有看起来的东西就像一个减号(也许是因为你在像Microsoft Word这样奇怪的东西中编辑了文件)复制并粘贴了一些搞乱角色的来源代码。
Haskell将无效字符打印为“?”因为,据它所知,你的输出终端不支持显示坏字符所需的编码。 (这是在Windows环境中运行Haskell时的常见问题,但如果事情设置奇怪,可能会在其他平台上发生。)
使用正确的文本编辑器打开源文件,突出显示“减号”并在键盘上重新键入。在西班牙语键盘上,这应该是右下移键的左侧键;在美国键盘上,它位于零键的右侧。
如果失败,请尝试将您自己的程序从Stack Overflow复制并粘贴到一个全新的文本文件中并编译 - 从您的问题中复制和粘贴对我们其他人来说正常。
答案 1 :(得分:1)
在我看来,这里存在两个问题:
sumatoria
,而您的功能是summation
; n > 1
和n == 1
是否相当不安全。我们可以通过sumatoria
替换summation
来解决问题,并使警卫更安全:
summation :: Integer -> Integer
summation n
| n >= 1 = n + summation (n-1)
| otherwise = 0
现在它应该工作了。我们使用otherwise = 0
,以便输入0
或负数时,我们会获得0
。
尽管如此,我们仍然可以改进这项功能。首先,我们不应仅限于Integer
s。我们可以使用任何Num
个a
Ord
种summation :: (Num a, Ord a) => a -> a
summation n
| n > 1 = n + summation (n-1)
| otherwise = 0
。所以我们可以将其重写为:
1..n
此外,0..n
或summation :: 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
要求Integral
为sum
。如果乘法,增量和除法都是 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