我是函数式编程的新手。我有一个基本问题。
我正在使用 Hugs 解释器,
我想用 Haskell 写一个函数;我浏览了几个教程,但我没有得到它。
fact :: Int -> Int
fact n = if n == 0 then
1
else
n * fact (n-1)
这给了我一个语法错误:-S
ERROR - Syntax error in input (unexpected `=')
我是函数式编程的新手。我有一个基本问题。
我正在使用 Hugs 解释器,
我想用 Haskell 写一个函数;我浏览了几个教程,但我没有得到它。
fact :: Int -> Int
fact n = if n == 0 then
1
else
n * fact (n-1)
这给了我一个语法错误:-S
ERROR - Syntax error in input (unexpected `=')
我假设你在交互式提示中输入了这个。遗憾的是,这些在 Haskell 中是相对原始的 - 复杂的定义,例如fact
, 不能在提示符下输入,至少与您通常编写它们的方式不同。
您需要将函数定义等放入模块中,然后通过 (eg) 加载它们:load fact.hs
。有专门针对 Hugs 的资源,提供有关此主题和其他主题的更多信息(我使用http://cvs.haskell.org/Hugs/pages/hugsman/index.html来检查我的假设)。
另请注意,缩进很重要,因此即使在模块中,代码也不会像您在此处发布的那样工作。这些教程将有正确的版本。如果没有,它们就没用了,你应该忘记它们。
语法不正确。在 Haskell 中,空格很重要,就像在 Python 中一样。更具体地说,如果您的文本从一行的第一列开始,解释器会认为这是一个顶级声明。正确的语法是(例如):
fact :: Int -> Int
fact n = if n == 0
then 1
else n * fact (n-1)
如果您愿意,也可以将 if 放在一行中。因此,如果您使用交互式提示,您可以这样做:
λ> let fact n = if n == 0 then 1 else n * fact (n-1)
请注意,您需要使用let
才能在提示符上定义函数(至少这是在 GHCi 中完成的方式,我不确定 Hugs)。最好将它们放在单独的文件中,然后将其加载到解释器中。但无论如何,在我看来,一个更好的解决方案会使用模式匹配:
fact :: Int -> Int
fact 0 = 1
fact n = n * fact (n-1)
在这里,解释器会将函数的第一个参数与列出的可能情况进行模式匹配。因此,如果第一个参数为 null,则结果为 1,否则递归应用该函数。
创建一个文件,例如,fact.hs
-- copying cedric's nicely formatted code
fact :: Int -> Int
fact n = if n == 0
then 1
else n * fact (n-1)
这就是真正需要在那里的一切。当你想制作真正的模块时,你应该做一些额外的事情。
现在,从同一个文件夹中打开 ghci。在 ghci 提示符下,使用:l
命令加载“模块”
Prelude> :l fact.hs
[1 of 1] Compiling Main ( fact.hs, interpreted )
Ok, modules loaded: Main.
*Main> fact 3
6
*Main> fact 10
3628800
我认为这与 Hugs 的过程非常相似。我认为拥抱要求文件名大写。ghci 只是创建一个“主”模块并将您的代码放入其中;这就是为什么提示从Prelude>
变为*Main>
当我处理小型 Haskell 函数时,我通常会打开两个终端:一个用于 vim,一个用于 ghci。当我在 vim 中更改文件(并保存它)时,我只是:r
在 ghci 中使用来重新加载新定义。
*Main> :r
Ok, modules loaded: Main.
需要指出的是,写这个函数最优雅的方式是:
fac n = product [1..n]
有关详细信息,请参阅http://www.willamette.edu/~fruehr/haskell/evolution.html。