動態

詳情 返回 返回

用户定義函數—λ 演算 - 動態 詳情

λ 演算(lambda calculus)是一套用於研究函數定義、函數應用和遞歸的形式系統。 它
由阿隆佐·邱奇(Alonzo Church,1903年6月14日-1995年8月11日)和他的學生在20世
紀30年代引入。 邱奇運用λ演算在1936年給出判定性問題(Entscheidungsproblem)的
一個否定的答案。 這種演算可以用來清晰地定義什麼是一個可計算函數。 Lambda 演算
對函數式編程語言(如Lisp語言)有着巨大的影響,Lambda 演算可以被稱為最小的通用程
序設計語言。 它包括一條變換規則(變量替換)和一條函數定義方式,Lambda 演算之通
用在於,任何一個可計算函數都能用這種形式來表達和求值。因而,它等價於圖靈機。

從簡單的列子開始,首先是個恆等函數:
id(x) = x
代入一個變量 x,立即返回 x (恆等函數返回它的輸入值,不管它是什麼)。再來個方程式:
sqsum(x, y) = x*x + y*y
代入兩個變量 x 和 y,返回它們的平方和(xx + yy)。 接下來,從上面的兩個例子中褪去光彩的外衣,我們會發現 λ 演算(lambda calculus)的理念: 首先發現的是函數的功能其實與前面函數的名字沒有關係,存在一個匿名的形式來表達同樣的功能:

id(x) = x
等同於匿名式:(x) → x
sqsum(x, y) = x*x + y*y
等同於匿名式:(x, y) → x*x + y*y

箭頭的右側為函數體,指明返回的內容。 λ 演算式為了使匿名式區別其他的含義,在它前面加個 λ
符號,箭頭改為.後,因為有了點分隔符,參數也不需要括號:

匿名式:(x) → x
等同於 λ 演算式: λx.x
匿名式:(x, y) → x*x + y*y
等同於 λ 演算式: λxy.x*x + y*y

第二個發現的是函數的功能與函數中的參數名字選擇沒有關係,它們可以是任意符號,只要函數體中應用到的變量符號和參數符號相同即可:

匿名式:(x) → x
等同於:(y) → y
即:λx.x == λy.y
匿名式:(x, y) → x*x + y*y
等同於:(u, v) → u*u + v*v
即:λxy.x*x + y*y == λuv.u*u + v*v

最後發現的是需要輸入多個參數的函數,並不需要一次連續地代入,可以重新組織用返回一個僅一個 參數的函數來實現一樣的功能。 也就是説函數可以在代入參數的過程中,可以在時間上前後分開:

匿名式:(x, y) → x*x + y*y
等同於:x → (y → x*x + y*y)
λ 演算式: λxy.x*x + y*y
等同於: λx.λy.x*x + y*y

這個變換的過程稱為"Currying",柯里化(Currying)是把接受多個參數的函數變換成接受一個單一參數(最初函數的第一個參數)的函數, 並且返回用餘下的參數來計算結果的新函數。給定兩個參數:

((x, y) → x*x + y*y)(5, 2)
= 5*5 + 2*2 = 29
Currying 後:
((x → (y → x*x + y*y))(5))(2)
= (y → 5*5 + y*y)(2)
= 5*5 + 2*2 = 29

Currying 之前與之後,我們得到相同的結果。説明一點:在第一個參數賦值之後,x*x 變成一個常
數。 奇妙的是:一個函數接受一個參數並返回另一個接受餘下的參數的函數。

總結一下,λ 演算(lambda calculus)的思想:函數本身是數據,也是值,可以被傳遞,可以被計
算。 函數像數值、字符串等其他的常用數據類型一樣,是數據類型中的一等公民:

  • 函數可以動態創建。
  • 函數可以不依賴符號名稱而獨立存在。
  • 函數可以賦值給變量。
  • 函數可以作為參數傳遞給其他函數。
  • 函數可以作為其他函數的返回值。
  • 函數可以保存在數據結構中。
user avatar niandb 頭像 axiaoxin_blog 頭像 jianqiangdepaobuxie 頭像 moonbit 頭像
點贊 4 用戶, 點贊了這篇動態!
點贊

Add a new 評論

Some HTML is okay.