【问题标题】:Functions in HaskellHaskell 中的函数
【发布时间】:2011-08-03 22:58:53
【问题描述】:

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

我正在使用 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 functional-programming syntax-error read-eval-print-loop hugs


    【解决方案1】:

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

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

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

    【讨论】:

    • 正如 delnan 所暗示的,您必须使用不同的方式在 ghci 中编写函数定义。对于这个例子,你可以写“let fact n = if n == 0 then 1 else n * fact (n - 1)”
    • @Jeff: 只是它不是 GHCi ;) 我不确定同样的东西在 Hugs 中是否有效,尽管应该尝试一下。
    • 感谢我写给交互式提示的详细解释。你能解释或链接一个如何创建模块的教程吗?
    • @Sudantha:这不过是一个包含 Haskell 代码的文本文件。
    【解决方案2】:

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

    【讨论】:

    • 这在 Hugs 中是不可能的。 Hugs 无法在解释器中定义函数。
    • 如何从 ghci 命令行定义你的两行函数 [fact 0=1, fact n=n*fact(n-1)]?使用两个 let 语句意味着后半部分替换了前半部分。是否有任何语法可以以某种方式将两种事实模式放在同一个 let 语句中?
    【解决方案3】:

    创建一个文件,例如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 中更改文件(并保存)时,我只是在 ghci 中使用 :r 重新加载新定义。

    *Main> :r
    Ok, modules loaded: Main.
    

    【讨论】:

      【解决方案4】:

      需要提一下,这个函数最优雅的写法是:

      fac n = product [1..n]
      

      详情请见http://www.willamette.edu/~fruehr/haskell/evolution.html

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-08-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-02-19
        • 2019-10-14
        • 2014-11-01
        相关资源
        最近更新 更多