2009-05-23 56 views
7

拿這個例子的代碼(忽略它是暫時效率極其低下)遞歸lambda表達式

let listToString (lst:list<'a>) = ;;' prettify fix 

    let rec inner (lst:list<'a>) buffer = ;;' prettify fix 
     match List.length lst with 
     | 0 -> buffer 
     | _ -> inner (List.tl lst) (buffer + ((List.hd lst).ToString())) 

    inner lst "" 

這是我一直在F#跨越未來一個共同的模式,我需要有一個內部函數誰遞歸本身超過一些價值 - 我只需要這個函數一次,是否有任何可能從它內部調用一個lambda自我(一些魔術關鍵字或其他)?我想代碼看起來像這樣:

let listToString2 (lst:list<'a>) = ;;' prettify fix 

    (fun 
     (lst:list<'a>) buffer -> match List.length lst with ;;' prettify fix 
           | 0 -> buffer 
           | _ -> ##RECURSE## (List.tl lst) (buffer + ((List.hd lst).ToString())) 
    ) lst "" 

但正如你所期望的有沒有辦法指在自身內部匿名函數,在這裏我把## RECURSE ##

回答

17
這是需要

是的,可以使用所謂的y-combinators(或fixed-point combinators)。例如:

let rec fix f x = f (fix f) x 

let fact f = function 
| 0 -> 1 
| x -> x * f (x-1) 


let _ = (fix fact) 5 (* evaluates to "120" *) 

我不知道F#的文章,但這個haskell entry也可能會有所幫助。

但是:如果有其他選擇,我不會使用它們 - 它們很難理解。

你的代碼(這裏省略了類型註釋)是一個標準的構造,更富有表現力。

let listToString lst = 

    let rec loop acc = function 
     | [] -> acc 
     | x::xs -> loop (acc^(string x)) xs 

    loop "" lst 
1

注意,雖然你說你使用的功能只有一次,在技術上你是指它的名字兩次,這就是爲什麼它是有道理的,給它一個名字。