![](/img/trans.png)
[英]How does the outermost evaluation strategy evaluate partial application of a function and application of a curried function
[英]Curried function defined in terms of its own partial application
以下 SML 代碼取自華盛頓大學課程的家庭作業。 (具體來說,它是提供的代碼的一部分,以便學生可以使用它來完成課程網頁上列出的家庭作業 3。)我不是在這里尋求家庭作業幫助——我想我明白代碼在說什么。 我不太明白的是,如何允許根據自己的部分應用來定義咖喱 function。
datatype pattern =
WildcardP
| VariableP of string
| UnitP
| ConstantP of int
| ConstructorP of string * pattern
| TupleP of pattern list
fun g f1 f2 p =
let
val r = g f1 f2 (* Why does this not cause an infinite loop? *)
in
case p of
WildcardP => f1 ()
| VariableP x => f2 x
| ConstructorP(_,p) => r p
| TupleP ps => List.foldl (fn (p,i) => (r p) + i) 0 ps
| _ => 0
end
function 綁定是一個遞歸定義,它利用了pattern
的數據類型綁定中的遞歸結構。 但是當我們到達val r = g f1 f2
,為什么這不會導致執行思考,“等等,什么是g f1 f2
f1
這就是我通過將f2
傳遞給 function 得到的,該g
.那么讓我們go回到g
的定義“並進入一個無限循環?
function g
永遠不會使用f1
和f2
以外的任何值遞歸調用。 按理說g f1 f2
不管調用多少次,總會得到相同的結果。
我建議閱讀https://smlhelp.github.io/book/的柯里化部分的暫存部分。
一個更簡單、更簡單的例子,展示了同樣的事情。 一個人為的 function 向下計數一個 int 直到提供的 function 返回 true。
fun x (f: int -> bool) (a: int) : int =
let
val g = x f
in
if a = 0 then 0
else if f a then a
else g (a - 1)
end
我們也可以看到將其轉換為 OCaml 也是如此。
let rec x f a =
let g = x f in
if a = 0 then 0
else if f a then a
else g (a - 1)
使用 lambda 微積分抽象,咖喱 function g
是g = (^f1. (^f2. (^p. ...body...)))
等等
g a b = (^f1. (^f2. (^p. ...body...))) a b
= (^f2. (^p. ...body...)) [a/f1]
= (^p. ...body...) [a/f1] [b/f2]
部分應用程序只生成內部 lambda function 與關閉的兩個參數綁定配對 - 根本不進入正文。
So defining r = g f1 f2
is just as if defining it as the lambda function, r = (^p. g f1 f2 p)
(this, again, is LC-based, so doesn't deal with any of the SML-特定的東西,比如類型)。
並且定義一個 lambda function (一個閉包)只是一個恆定時間的操作,它不會進入g
function 體,所以更不用說無限循環了。
這些都是等價的,並且都沒有使它看起來可能存在無限遞歸:
您可以用r
中的值替換 r,
fun g f1 f2 p =
case p of
WildcardP => f1 ()
| VariableP x => f2 x
| ConstructorP(_,p) => g f1 f2 p
| TupleP ps => List.foldl (fn (p,i) => (g f1 f2 p) + i) 0 ps
| _ => 0
或“提升”模式匹配,
fun g f1 _ WildCardP = f1 ()
| g _ f2 (VariableP x) = f2 x
| g f1 f2 (ConstructorP (_, p)) = g f1 f2 p
| g f1 f2 (TupleP ps) = List.foldl (fn (p,i) => (g f1 f2 p) + i) 0 ps
| g _ _ _ = 0
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.