Haskell“fix”关键字在声明递归lambda函数时失败

时间:2016-02-19 09:49:32

标签: haskell recursion lambda

似乎函数应该具有递归的名称(为了调用自身),那么lambda函数如何递归?

我搜索了维基百科,它说这可以通过“Y-combinator”来完成。我没有太多的数学理论背景,只是告诉我“Y-combinator”是由Haskell自己发现的。在Haskell语言中称为“fix”关键字,我尝试过:

Prelude> let fact = fix (\f n -> if n == 0 then 1 else n * (f (n-1)))

<interactive>:17:12: Not in scope: ‘fix’

似乎失败了,但是如何使用“fix”关键字来做我所期望的呢?

2 个答案:

答案 0 :(得分:12)

<?php include 'connect.php'; include 'functions.php'; if(isset($_POST['submit'])){ $username = mysqli_real_escape_string($con, $_POST['username']); $password = md5(mysqli_real_escape_string($con, $_POST['password'])); if(empty($username) or empty($password)){ $message = '&nbsp<p>Polja su prazna !</p>'; } else { $check_login = mysqli_query($con, "SELECT id, user_level FROM korisnici WHERE username='".$username."' AND password='".$password."'"); if(mysqli_num_rows($check_login) == 1){ $run = mysqli_fetch_array($check_login); $user_id = $run['id']; $user_level = $run['user_level']; $_SESSION['user_id'] = $user_id; header("Location: admin"); }else{ $message = '&nbsp<p>Pogrešno Korisničko ime ili Lozinka!</p>'; } } } ?> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, minimumscale=1.0, maximum-scale=1.0" /> <title>Login - Admin</title> <link rel='stylesheet' href='style.css' type='text/css' /> <?php include 'header.php'; ?> </head> <body > <div id="container_vanjski"> <div id="container"> <form method="post"> <br/> <?php echo (isset($message) ? $message : ''); ?> <br/> <div id="log"> <label for="username">Korisničko ime:</label><input type="text" name="username" /><br /> <label for="password">Lozinka:</label><input type="password" name="password" /><br /> <br /> <input type="submit" name="submit" value="Prijava" id="button" /> </div> </form> </div> <?php include 'footer.php'; ?> </div> </body> </html> 不是关键字,它是fix模块中定义的函数。因此,要使用它,您必须导入该模块。

Data.Function

或GHCi:

import Data.Function

答案 1 :(得分:2)

fix定义为:

fix :: (a -> a) -> a
fix f = let x = f x in x

所以它扩展为f (f (f (f ...))),即输入函数f的嵌套应用程序的无限序列到某个参数x

你可以给你的lambda函数一个顶级定义,例如

factF f n = if n == 0 then 1 else n * f (n - 1)

或等效地:

factF :: (Int -> Int) -> (Int -> Int)
factF f = \n -> if n == 0 then 1 else n * f (n - 1)

您可以将此功能提供给fix以获取函数(Int -> Int),即

fact :: (Int -> Int)
fact = fix factF

如果你扩展这个定义,你得到

factF (factF (factF (factF ...)))
=> \n -> if n == 0 then 1 else (factF (factF (factF ...)))

由于懒惰,factF的重复申请仅在n /= 0时进行评估,因此应用于0的上述功能将立即评估为1。

您可以在此扩展中看到factF作为参数提供给自身,然后它应用于较小版本的n。由于factN与lambda函数相同,所以同样的事情发生在那里 - lambda中的参数f是lambda本身,然后它可以递归调用。