2013-04-29 82 views

回答

1
let rec sum a = 
    match a with 
    |Nil -> 0 
    |Link(s,t) -> s+(sum (!t)) 
+0

我不認爲你可以有一個'_'被允許在模式匹配中,對吧?你有_ +(sum(!t)) – 2013-04-29 22:39:03

+0

@JohnOriely我改變它只是爲了確定,已經測試它,它的工作原理 – 2013-04-29 22:56:19

+0

我實際上錯誤地鍵入了錯誤的聲明,這就是爲什麼它不工作。你能再看一次嗎,謝謝! – 2013-04-29 23:02:18

1

我試過你的例子,它不起作用,所以我確實修復了它。

type lists = Nil | Link of (int * (lists ref)) 

let list1 = Link(3, ref (Link (2, ref Nil))) 
let list2 = Link(6, ref (Link (4, ref Nil))) 
let list3 = Link(9, ref (Link (6, ref Nil))) 

let rec sum = function  // or let rec sum list = match list with 
    | Nil    -> 0 
    | Link(head, tail) -> head + sum !tail 

你並不需要定義Integer of int,如果你這樣做,你必須與Integer

+0

嗯有趣,當我嘗試這個時,它說'h'和'sum!t'類型不匹配 – 2013-04-29 22:49:32

+0

它適用於我。你確定?從頭開始嘗試代碼,我只是重命名了一些變量。 – Gustavo 2013-04-29 22:51:31

+0

啊我在聲明時輸入的行不正確。類型rNumber = int的整數;; type lists =無| (rNumber *(lists ref))的鏈接它假設是「rNumber」不是整數。這就是爲什麼我得到一個錯誤,說明'int'類型不匹配'rNumber'。我將如何解決這個問題?感謝您一直以來的幫助! – 2013-04-29 23:01:32

10

F#標記所有的數字有一個內置的「鏈接列表」(通用)型 - 這只是叫list,並且已經有一個函數來計算sum

let list1 = [2; 3; 5] 
List.sum list1 

列表上的任意操作都可以使用遞歸函數寫:

let rec sum l = 
    match l with 
    | [] -> 0 
    | head::tail -> head + (sum tail) 

,但在大多數情況下,它是足夠使用內置fold功能:

let sum l = 
    List.fold (fun total element -> total + element) 0 l 

還要注意的是上面的「天真」遞歸函數不tail-recursive,所以當應用到它會崩潰很長的名單。尾遞歸的實現將是這樣的:

let sum l = 
    let rec sumAcc acc l = 
    match l with 
     | [] -> acc 
     | head::tail -> sumAcc (acc+head) tail 
    sumAcc 0 l 

,基本上是什麼fold一樣。

(我加入了這個答案,以防有人不知道這個網頁上的F#的土地 - 他/她可以得到一個錯誤的想法,有關名單F#中支持)

1

只是爲了完整起見:

let sum l = 
    l 
    |> List.reduce (+) 

也會訣竅。類型推斷將推斷l至是int列表,所以如果你需要一些其他數據類型,你可以這樣做(例如多頭列表):

let sum (l:list<int64>) = 
    l 
    |> List.reduce (+) 

或本:

let inline sum l = 
     l 
     |> List.reduce (+) 

內聯將泛化sum函數來處理任何提供名爲「+」的靜態函數的類型。要使用它,你就會有這樣的代碼:

let mylist = [1;2;3;4] 
let sumOfMyList = sum mylist;; 

我還要說,在我的經驗,使用列表褶皺和相關的功能比滾動自己的遞歸函數的更好方法。