我有這樣的說法:混淆SML聲明
let val x =
let val x = 5
in(fn y =>(y,x+y))
end
in
let val y=3 and z=10
in x z
end
end;
輸出是:
(10,15)
我一直在試圖跟蹤這個答案是如何產生的,但我感到困惑。有沒有更好的方法來寫這個,這將有助於我理解在哪裏使用哪些變量?謝謝!
我有這樣的說法:混淆SML聲明
let val x =
let val x = 5
in(fn y =>(y,x+y))
end
in
let val y=3 and z=10
in x z
end
end;
輸出是:
(10,15)
我一直在試圖跟蹤這個答案是如何產生的,但我感到困惑。有沒有更好的方法來寫這個,這將有助於我理解在哪裏使用哪些變量?謝謝!
首先,一些的α-轉化率:
let val fnPairOfInputAndInputPlus5 =
let val five = 5
in (fn input => (input, five + input))
end
in let val ignored = 3 and input = 10
in fnPairOfInputAndInputPlus5 input
end
end;
該代碼被證明當聲明的函數值,在聲明範圍未結合的值,如值five
,被「封閉的」由該聲明(因此稱爲「關閉」)。因此函數總是返回一個由輸入和輸入加上五個組成的對。
您可以將其簡化爲
let fun f y = (y,5+y)
val y=3 and z=10
in
f z
end;
注意y的兩個實例都是獨立的。 x(我已經消除)的內部出現獨立於外部(現在重命名爲f)。
可以通過手動評估和詳細說明來理解。
與您最初的表達開始:
let val x =
let val x = 5
in (fn y => (y,x + y))
end
in
let val y = 3 and z = 10
in x z
end
end;
2,3,4號線是一個類型爲函數的表達式,如您在in
部分看到。它不取決於任何外部環境,所以根據let
中給出的約束,可將其簡化爲fn y => (y, 5 + y)
,用x
替換爲5
。
所以你現在有這樣的:
let val x = fn y => (y, 5 + y)
in
let val y = 3 and z = 10
in x z
end
end;
的x
置換後(並去除其在那麼現在不再需要更多的let
的):
let val y = 3 and z = 10
in (fn y => (y, 5 + y)) z
end;
注意y
出現在(y, 5 + y)
被綁定到函數的參數,而不是3
。沒有提及這個外部的y
,所以它的招標可能會被刪除。
現在您有:
let z = 10
in (fn y => (y, 5 + y)) z
end;
代z
到10
和去除let
這是沒有必要的任何更多,您可以:
(fn y => (y, 5 + y)) 10;
這是一個功能應用。您可以評估它,得到:
(10, 5 + 10);
,讓你注意到了最後和一定的成果:
(10, 15);
謝謝!這清理了很多。我仍然對'fnPairofinputAndInputPlus5 input'是什麼感到困惑。你用一個輸入參數來調用這個值? – user2796815
沒錯。 ML中的函數調用符號只是'f x'或'(f x)'函數'f'和參數'x'。兩個參數的函數可以接受一個單獨的*元組*,其中兩個參數'f(x,y)',或者它們可以* curried *函數'fxy' ='(fx)y' ='((fx)y) '。在後一種情況下'f x'返回另一個函數。 –