GHCi 中特殊情况下的函数定义
Function definition by special cases in GHCi
来自 Haskell tutorial:
We can write functions on integers by cases.
-- 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
我错过了什么?
ghci 是一个交互式工具,因此允许在函数已经定义时重新定义它。在您的情况下,它不会将其视为两行函数定义,而是将其视为定义它的两次尝试。所以 f n = print n
覆盖 f 0 = print 999
而不是完成它。
在ghci中输入多行语句有一个特殊的语法。你需要做
Prelude> :{
Prelude> let foo 0 = print 999
Prelude> foo n = print n
Prelude> :}
要在 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
来自 Haskell tutorial:
We can write functions on integers by cases.
-- 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
我错过了什么?
ghci 是一个交互式工具,因此允许在函数已经定义时重新定义它。在您的情况下,它不会将其视为两行函数定义,而是将其视为定义它的两次尝试。所以 f n = print n
覆盖 f 0 = print 999
而不是完成它。
在ghci中输入多行语句有一个特殊的语法。你需要做
Prelude> :{
Prelude> let foo 0 = print 999
Prelude> foo n = print n
Prelude> :}
要在 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