2013-01-17 82 views
2

這裏就是我這麼遠......SML:我如何傳遞一個函數列表並返回刪除了所有負面實數的列表?

fun positive l1 = positive(l1,[],[]) 
| positive (l1, p, n) = 
     if hd(l1) < 0 
     then positive(tl(l1), p, n @ [hd(l1]) 
     else if hd(l1) >= 0 
     then positive(tl(l1), p @ [hd(l1)], n) 
     else if null (h1(l1)) 
     then p 

是的,這是對我的教育目的。我在大學攻讀ML課程,我們必須編寫一個程序來返回列表中最大的整數,我希望超出這個範圍,看看我是否也可以刪除它。

另外,如果可能的話,任何人都可以給我一個體面的ML書或引子?我們的課文並沒有很好地解釋事情。

回答

2

你沒有提到你的代碼沒有輸入。

您的第一個函數子句只有變量l1,它用於遞歸。然而在這裏它被用作三元組的第一個元素,它被作爲參數給出。這與SML使用的Hindley-Milner類型系統並不完全一致。這也許是更好的通過非正式的想法看出:

讓我們首先假設l1有型'a,因此功能必須採取該類型的參數,並返回了未知的東西'a -> ...開始。但是,在右側創建的參數(l1, [], [])必須具有類型'a * 'b list * 'c list。但是,由於它作爲函數的參數傳遞,那必然也意味着'a等於'a * 'b list * 'c list,顯然不是這種情況。

顯然這不是你的原意。看起來你的意圖是有一個函數,它將一個列表作爲參數,然後同時有一個遞歸輔助函數,它需要兩個額外的累加參數,即原始列表中的正數和負數列表。

要做到這一點,你至少需要給你的助手函數另一個名字,這樣它的定義將不會重新定義原始函數的定義。 然後你有一些選擇,這個輔助函數應該在哪個範圍內。一般來說,如果調用這個輔助函數而不是從「main」函數以外沒有任何意義,那麼它不應該放在「主」功能之外的範圍。

fun positive xs = 
    let 
     fun positive' ys p n = ... 
    in 
     positive' xs [] [] 
    end 

這樣的輔助函數positives'不能被稱爲positive功能外:這可以通過使用一個讓這樣的結合來完成。

有了這個照顧你的原代碼還有一些問題。

  • 由於您只返回正整數的名單,也沒有必要跟蹤 消極的。

  • 您應該使用模式匹配來分解列表元素。通過這種方式,您可以消除採用列表的首尾的方式,並且還需要驗證列表中是否存在頭尾的 。

    fun foo []  = ... (* input list is empty *) 
        | foo (x::xs) = ... (* x is now the head, and xs is the tail *) 
    
  • 你不應該使用追加操作符(@),只要你能避免它(你總是可以)。 問題是,當您在左側 側有一個巨大的列表並且在右側有一個小列表(右側通常是這種情況,因爲它主要用於 ),所以它有可怕的運行時間追加單個元素)。因此它應該被認爲是不好的 練習使用它。

    但是存在一個很簡單的解決這個,這是始終拼接元素 在列表的前面(構建以相反的順序列表),然後返回它的最後一件事,當剛剛倒車列表 (預期爲了使它):

    fun foo [] acc = rev acc 
        | foo (x::xs) acc = foo xs (x::acc) 
    

鑑於這些小票,我們結束了,看起來像這樣

fun positive xs = 
    let 
     fun positive' [] p = rev p 
     | positive' (y::ys) p = 
      if y < 0 then 
      positive' ys p 
      else 
      positive' ys (y :: p) 
    in 
     positive' xs [] 
    end 
功能
1

您是否瞭解了List.filter?這可能是適當的 - 它需要一個'a -> bool類型的函數(這是一個謂詞)和一個類型爲'a list的列表,並返回一個只包含謂詞評估爲true的元素的列表。例如:因爲你要比較使用int版本的<整數

List.filter (fn x => Real.>= (x, 0.0)) [1.0, 4.5, ~3.4, 42.0, ~9.0] 

您現有的代碼將無法正常工作。代碼hd(l1) < 0將在int列表上工作,而不是real的列表。標準ML不會自動強制數字文字。必須明確寫出0.0,並使用Real.< (hd(l1), 0.0)進行測試。

如果您不想使用標準庫中的filter,您可以考慮自己如何實現filter。這裏有一種方法:

fun filter f [] = [] 
    | filter f (h::t) = 
     if f h 
     then h :: filter f t 
     else filter f t 
相關問題