【问题标题】:Function definition by special cases in GHCiGHCi中特殊情况下的函数定义
【发布时间】:2017-03-04 07:15:21
【问题描述】:

来自 Haskell tutorial

我们可以按大小写整数函数。

-- Compute the sum of the integers from 1 to n.
sumtorial :: Integer -> Integer
sumtorial 0 = 0
sumtorial n = n + sumtorial (n-1)

但是,当我尝试它时会发生以下情况:

$ ghci
GHCi, version 8.0.1: http://www.haskell.org/ghc/  :? for help
Prelude> foo 0 = print 999
Prelude> foo n = print n
Prelude> foo 0
0

我错过了什么?

【问题讨论】:

    标签: haskell ghci


    【解决方案1】:

    要在 GHCi 中完全按照其编写方式使用这些定义(即在单独的行中使用多个方程或类型签名),您需要通过 :{:} 分隔符在 GHCi 中使用多行输入:

    GHCi> :{
    GHCi| foo 0 = print 999
    GHCi| foo n = print n
    GHCi| :}
    GHCi> foo 0
    999
    

    另一种选择是使用+m 选项在会话的其余部分启用多行输入。不过,在这种情况下,您还需要一个显式的let,因为没有它,GHCi 将无法判断您是否要继续定义:

    GHCi> :set +m
    GHCi> let foo 0 = print 999
    GHCi|     foo n = print n
    GHCi| 
    GHCi> foo 0
    999
    

    (您可以使用:unset +m 关闭+m。)

    另一种可能性是完全避免换行,并使用明确的大括号和分号:

    GHCi> foo 0 = print 999; foo n = print n
    GHCi> foo 0
    999
    

    在多行输入选项之间,我个人更喜欢 :{:} 而不是 +m,因为它们对我通常如何表达我的定义需要的更改较少,而且如果我粘贴,更有可能立即工作其他地方的代码。

    至于你的输入方式为什么不起作用,那是因为,除非你使用多行输入,否则在不同的 GHCi 行中绑定到相同名称会相互影响:

    GHCi> x = 3
    GHCi> x = 4
    GHCi> x
    4
    

    如果我们注意到我们从let-表达式链中得到相同的行为,这似乎就不那么令人惊讶了:

    GHCi> let x = 3 in let x = 4 in x
    4
    

    【讨论】:

    • :{:} 是 GHCi 命令{;} 是我所说的显式分隔符。 :)
    • @WillNess 一个有效点。我把这句话改写了一下。
    【解决方案2】:

    ghci 是一个交互式工具,因此允许在函数已经定义时重新定义它。在您的情况下,它不会将其视为两行函数定义,而是将其视为定义它的两次尝试。所以f n = print n 覆盖f 0 = print 999 而不是完成它。

    要在 ghci 中输入多行语句,有一个特殊的语法。你需要做的

    Prelude> :{
    Prelude> let foo 0 = print 999
    Prelude>     foo n = print n
    Prelude> :}
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-04
      • 1970-01-01
      • 2015-10-21
      • 2016-10-23
      • 1970-01-01
      • 1970-01-01
      • 2017-04-07
      相关资源
      最近更新 更多