3

我是函数式编程的新手。我有一个基本问题。

我正在使用 Hugs 解释器,

我想用 Haskell 写一个函数;我浏览了几个教程,但我没有得到它。

fact :: Int -> Int
fact n = if n == 0 then
1
else
n * fact (n-1)

这给了我一个语法错误:-S

ERROR - Syntax error in input (unexpected `=')
4

4 回答 4

6

我假设你在交互式提示中输入了这个。遗憾的是,这些在 Haskell 中是相对原始的 - 复杂的定义,例如fact, 不能在提示符下输入,至少与您通常编写它们的方式不同。

您需要将函数定义等放入模块中,然后通过 (eg) 加载它们:load fact.hs。有专门针对 Hugs 的资源,提供有关此主题和其他主题的更多信息(我使用http://cvs.haskell.org/Hugs/pages/hugsman/index.html来检查我的假设)。

另请注意,缩进很重要,因此即使在模块中,代码也不会像您在此处发布的那样工作。这些教程将有正确的版本。如果没有,它们就没用了,你应该忘记它们。

于 2011-04-12T14:33:51.027 回答
4

语法不正确。在 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,否则递归应用该函数。

于 2011-04-12T14:36:45.090 回答
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.
于 2011-04-12T18:09:02.913 回答
1

需要指出的是,写这个函数最优雅的方式是:

fac n = product [1..n]

有关详细信息,请参阅http://www.willamette.edu/~fruehr/haskell/evolution.html

于 2011-04-12T20:05:40.550 回答