2013-01-13 94 views
2

我對SML非常陌生,我正在嘗試清單練習。目標是總結列表的前幾個數字並創建一個新列表。例如,輸入列表[1, 4, 6, 9]將返回[1, 5, 11, 20]SML清單彙總

這是我迄今爲止的解決方案,但我認爲問題在於我如何定義函數。

fun rec sum:int list -> int list = 
    if tl(list) = nil then 
     hd(list) 
    else 
     hd :: sum((hd(tail) + hd(tl(list)))::tl(tl(list))); 

回答

2

試試這個 -

fun recList ([], index, sum) = [] 
    | recList (li, index, sum) = 
    if index=0 then 
     hd li :: recList (tl li, index+1, hd li) 
    else 
     sum + hd li :: recList (tl li, index+1, sum + hd li) 

fun recSum li = recList (li, 0, 0) 

在你的情況 -

recSum([1,4,6,9]) ; 

會給

val it = [1,5,11,20] : int list 

也不要使用rec有趣的名字 - 它的關鍵字。

3

除此之外,您使用rec作爲函數名稱,那麼您有一些小問題需要處理。

  • 您所做的顯式類型註釋被視爲函數結果的註釋。 因此,根據您所寫的內容,它應該返回一個函數,而不是預期的 列表。這顯然是從下面的例子中看出:

    - fun rec_ sum : int list -> int list = raise Domain; 
    val rec_ = fn : 'a -> int list -> int list 
    
  • 你應該小心使用的頭部和尾部的功能,當你不這樣做的 號碼列表中的元素的任何檢查。這可以通過長度函數來完成,或者通過模式匹配元素的數量(甚至更容易且通常更好)來完成。

  • 您的代碼包含sum作爲函數調用,tail作爲變量。變量尾從未定義過 ,並且使用sum作爲函數調用,這讓我相信您實際上正在使用rec 作爲關鍵字,但不知道它的含義。

    當使用val關鍵字定義函數時,使用關鍵字rec。在這種情況下,rec是 需要能夠定義遞歸函數(不是很大的驚喜)。實際上,關鍵字fun 是val rec的語法糖(一種派生形式)。

下面3是如何可能已經做出例子:

的第一個是簡單,直接的解決方案。

fun sumList1 (x::y::xs) = x :: sumList1 (x+y::xs) 
    | sumList1 xs = xs 

第二個示例使用輔助函數,並添加參數(累加器)。該列表以相反的順序構造,以避免使用慢附加(@)運算符。因此,我們返回之前扭轉名單:

fun sumList2 xs = 
    let 
     fun sumList' [] acc = rev acc 
     | sumList' [x] acc = rev (x::acc) 
     | sumList' (x :: y :: xs) acc = sumList' (y+x :: xs) (x :: acc) 
    in 
     sumList' xs [] 
    end 

最後一個例子,表明它是如何小,容易就可以了,如果你使用標準列表功能。這裏使用左側的摺疊來遍歷所有元素。再次請注意,該列表是以相反的順序構建的,因此它與最後一步相反:

fun sumList3 []  = [] 
    | sumList3 (x::xs) = rev (foldl (fn (a, b) => hd b + a :: b) [x] xs)