2011-06-05 56 views
3

我想將此ML代碼翻譯成F#。通過翻譯ML的等效實現與F#

fun take ([], i) = [] 
    | take (x::xs, i) = if i > 0 then x::take(xs, i-1) 
           else []; 

我想這一個

let rec take n i = 
    match n,i with 
    | [], i -> [] 
    | x::xs, i -> if i > 0 then x::take(xs, i-1) 
          else []; 

let val = take [1;2;3;4] 3 

而這一次

let rec take input = 
    match input with 
    | ([], i) -> [] 
    | (x::xs, i) -> if i > 0 then x::take(xs, i-1) 
          else []; 

let val = take ([1;2;3;4] 3) 

但他們兩人給我一個錯誤take.fs(7,5): error FS0010: Unexpected keyword 'val' in binding。 F#代碼有什麼問題?

回答

7

由於val是F#中的保留關鍵字,因此不能將其用作值。 take的第一個版本是錯誤的,因爲take(xs, i-1)(元組形式)的類型與take n i(咖喱形式)的類型不同。這個作品:

let rec take n i = 
    match n, i with 
    | [], i -> [] 
    | x::xs, i -> if i > 0 then x::(take xs (i-1)) else [] 

let value = take [1;2;3;4] 3 

第二個版本在調用函數的方式上有錯誤。它可以被確定如下:

let rec take input = 
    match input with 
    | [], i -> [] 
    | x::xs, i -> if i > 0 then x::take(xs, i-1) else [] 

let value = take ([1;2;3;4], 3) // Notice ',' as tuple delimiter 

或者你也可以更接近寫信給你的ML功能:

let rec take = function 
    | [], i -> [] 
    | x::xs, i -> if i > 0 then x::take(xs, i-1) else [] 

let value = take ([1;2;3;4], 3) 
+0

對於第二個版本,我得到了'錯誤FS0003:這個值是不是一個函數,不能applied'錯誤,它似乎除了最後的';'以外,和我一樣。 – prosseek 2011-06-05 21:57:48

+0

不,你應該使用take([1; 2; 3; 4],3)而不是take([1; 2; 3; 4] 3)。注意','是兩個版本之間的區別。 – pad 2011-06-05 22:05:09

+0

我明白了。謝謝。 – prosseek 2011-06-05 22:08:14

9

我想補充幾點意見,我覺得寫在F#功能的最好方式是使用:

let rec take i n= 
    match n, i with 
    | [], i -> [] 
    | _, i when i <= 0 -> [] 
    | x::xs, i -> x::(take (i-1) xs) 

我做了兩個轉變:

  • 使用模式匹配來測試i <= 0(與if做同樣的事情,但看起來好一點)
  • 顛倒參數的順序,以便最重要的參數(輸入列表)是最後一個參數。這使得可以與流水線操作員很好地使用功能:

    [1;2;3;4] |> take 3