Haskell “哈斯克尔”;“固定”;关键字在声明递归lambda函数时失败

Haskell “哈斯克尔”;“固定”;关键字在声明递归lambda函数时失败,haskell,recursion,lambda,fixpoint-combinators,Haskell,Recursion,Lambda,Fixpoint Combinators,似乎一个函数应该有一个递归的名称(为了调用自己),那么lambda函数是如何递归的呢 我搜索了维基百科,它说这可以由一个“Y组合器”来完成。我没有太多的数学理论背景,它只是告诉我“Y-组合子”是哈斯克尔自己发现的。在Haskell语言中称为“fix”关键字,我尝试: Prelude> let fact = fix (\f n -> if n == 0 then 1 else n * (f (n-1))) <interactive>:17:12: Not in scope

似乎一个函数应该有一个递归的名称(为了调用自己),那么lambda函数是如何递归的呢

我搜索了维基百科,它说这可以由一个“Y组合器”来完成。我没有太多的数学理论背景,它只是告诉我“Y-组合子”是哈斯克尔自己发现的。在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’
Prelude>let fact=fix(\f n->如果n==0,则1,否则n*(f(n-1)))
:17:12:不在范围内:“修复”

似乎失败了,但如何使用“fix”关键字实现我的预期目标?

fix
不是一个关键字,它是在
数据.function
模块中定义的函数。因此,要使用它,必须导入该模块

import Data.Function
或在GHCi中:

:m Data.Function

fix
不是关键字,它是在
Data.function
模块中定义的函数。因此,要使用它,必须导入该模块

import Data.Function
或在GHCi中:

:m Data.Function

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 ...)))
由于懒惰,仅当
n/=0
时才会评估重复应用
factF
,因此应用于
0
的上述函数将立即评估为1


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

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 ...)))
由于懒惰,仅当
n/=0
时才会评估重复应用
factF
,因此应用于
0
的上述函数将立即评估为1

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