我对Haskell很新,我必须说我很困惑
我正在使用GHCi前奏曲
首先尝试创建一个阶乘
Prelude> factorial 0 = 1
Prelude> factorial n = n*factorial(n-1)
Prelude> factorial 2
*** Exception: stack overflow
Run Code Online (Sandbox Code Playgroud)
最终堆栈溢出.显然递归并没有停止.
Prelude> :t factorial
factorial :: Num t => t -> t
Run Code Online (Sandbox Code Playgroud)
然后阅读这篇文章如何在多行中的ghci中定义一个函数?
我发现我必须使用多行版本或大括号(顺便说一句,这是一个运算符吗?)
Prelude> let { fact 0 = 1 ; fact n = n * fact (n-1) }
Prelude> fact 5
120
Prelude> ::t fact
fact :: (Eq p, Num p) => p -> p
Run Code Online (Sandbox Code Playgroud)
要么
Prelude> :{
Prelude| facto 0 = 1
Prelude| facto n = n*facto(n-1)
Prelude| :}
Prelude> facto 4
24
Prelude> :t facto
facto :: (Eq p, Num p) => p -> p
Run Code Online (Sandbox Code Playgroud)
所以,我的问题是,为什么第一个错误,在这种情况下发生了什么,为什么第二个和第三个工作,并且从:t函数的结果,它们似乎至少导致完全相同的定义.
为什么第一个是错的,在这种情况下会发生什么
因为您定义了两个具有相同名称的函数.
首先你定义:
factorial 0 = 1
Run Code Online (Sandbox Code Playgroud)
稍后你定义:
factorial n = n*factorial(n-1)
Run Code Online (Sandbox Code Playgroud)
但是Haskell会将第二个因子视为一个更局部的变量,因此第二个函数定义隐藏了前一个.因此,第一行(factorial 0 = 1)不再是定义的一部分.因此Haskell将进行评估factorial 2 -> 2 * factorial 1 -> 2 * 1 * factorial 0 -> 2 * 1 * 0 * factorial (-1) -> ....
为什么第二和第三个工作
因为在这里定义了一个函数,Haskell将这两个子句解释为同一函数的两个子句.与:t function你取得同样的事实,只是巧合.
请注意,以上内容仅适用于GHCi.如果您使用ghc编译器,它当然会将您的所有语句视为相同函数定义的一部分.如果您混合使用两个函数的子句(例如,首先a 0 = 0,然后b 0 = 0,然后a n = n),则会出现关于*同一函数的多个定义的错误.