如何不用if-then-else语句在haskell中编写递归阶乘函数 fac n=如果n=fac

如何不用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

我不知道如何编写没有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 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可能有太多处理布尔的特殊方法)