2013-12-16 145 views
3

我有這樣的說法:混淆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) 

我一直在試圖跟蹤這個答案是如何產生的,但我感到困惑。有沒有更好的方法來寫這個,這將有助於我理解在哪裏使用哪些變量?謝謝!

回答

4

首先,一些的α-轉化率:

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,被「封閉的」由該聲明(因此稱爲「關閉」)。因此函數總是返回一個由輸入和輸入加上五個組成的對。

+0

謝謝!這清理了很多。我仍然對'fnPairofinputAndInputPlus5 input'是什麼感到困惑。你用一個輸入參數來調用這個值? – user2796815

+0

沒錯。 ML中的函數調用符號只是'f x'或'(f x)'函數'f'和參數'x'。兩個參數的函數可以接受一個單獨的*元組*,其中兩個參數'f(x,y)',或者它們可以* curried *函數'fxy' ='(fx)y' ='((fx)y) '。在後一種情況下'f x'返回另一個函數。 –

3

您可以將其簡化爲

let fun f y = (y,5+y) 
    val y=3 and z=10 
in 
    f z 
end; 

注意y的兩個實例都是獨立的。 x(我已經消除)的內部出現獨立於外部(現在重命名爲f)。

0

可以通過手動評估和詳細說明來理解。

與您最初的表達開始:

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; 

z10和去除let這是沒有必要的任何更多,您可以:

(fn y => (y, 5 + y)) 10; 

這是一個功能應用。您可以評估它,得到:

(10, 5 + 10); 

,讓你注意到了最後和一定的成果:

(10, 15);