如何不用if-then-else语句在haskell中编写递归阶乘函数 fac n=如果n=fac
我不知道如何编写没有if语句的递归阶乘函数。我们的教授说了一些关于lambda演算的事情。模式匹配和保护是两种特别简单的方法。防护本质上是if-then-else的另一种语法;它们看起来像这样:如何不用if-then-else语句在haskell中编写递归阶乘函数 fac n=如果n=fac,haskell,lambda-calculus,Haskell,Lambda Calculus,我不知道如何编写没有if语句的递归阶乘函数。我们的教授说了一些关于lambda演算的事情。模式匹配和保护是两种特别简单的方法。防护本质上是if-then-else的另一种语法;它们看起来像这样: fac n = if n < 2 then 1 else n * fac (n-1) main = do putStrLn "Enter a number: " number <- getLine print $ number >>= fac fac
fac n = if n < 2 then 1 else n * fac (n-1)
main = do
putStrLn "Enter a number: "
number <- getLine
print $ number >>= fac
fac n = product [1..n]
特别是对于数字,这也基本上是一个if-then-else;但是对于编译器集成较少的数据类型,通常无法使用if-then-else进行仿真,并且通常会生成外观非常自然的代码
另一个非常好的方法是将递归推进到现有的Prelude函数中;在实践中,你越能发现迭代模式,你就越能通过不反复实现相同的循环来避免更多的错误。对于本例,您可以使用product
和特殊枚举语法:
fac 0 = 1
fac 1 = 1
fac n = n * fac (n-1)
一种更先进(更糟糕)的技术是定义一种新的数字;e、 g.Church数字允许数字的生产者驱动递归,消费者(此处,fac
)只提供基本情况。在这种样式中,您可能会看到如下内容:
fac n = if n < 2 then 1 else n * fac (n-1)
main = do
putStrLn "Enter a number: "
number <- getLine
print $ number >>= fac
fac n = product [1..n]
(但请注意,这需要一种非常特殊的数字——
fac
的类型肯定不是一种可以接受Int
或Integer
!)这个笑话在中得到了合乎逻辑的可怕结论。If/then/else和卫士实际上只是模式匹配的语法糖
fac n = fst (n (1,1) (\(prod, sum) -> (prod*sum, sum+1)))
去糖衣
if b
then c
else d
f x
| b = c
| d = e
f x = g
同样地
case b of
True -> c
False -> d
去糖衣
if b
then c
else d
f x
| b = c
| d = e
f x = g
因此,您始终可以直接使用case
。然而,有一个相当简单的优化,您可以手动执行。如果你看到
f x = case b of
True -> c
False -> case d of
True -> e
False = g
当p
由构造函数和文本组成时,可以用
case x == p of
True -> a
False -> b
试试这个:
case x of
p -> a
_ -> b
使用尾部递归:
factorial 0 = 1
factorial n = n * factorial (n - 1)
输出:
factorial n = f n 1
f 0 acc = acc
f n acc = f (n-1) (acc*n)
main = print $ factorial 5
不要忘记在
(==)
中的Bool
上进行模式匹配,这是Guard和if/then/else的作用。。(Haskell可能有太多处理布尔的特殊方法)