2017-01-29 77 views
0

我需要編寫一個函數,它需要一個列表並將其分成2個列表。第一個列表將保存位於奇數位置的元素,第二個列表保存位於偶數位置的元素。這裏是我的嘗試,給了我以下警告:將列表拆分成奇數和偶數位置的2個列表 - SML?

警告:類型乏不是一概而論,因爲 值的限制被實例化虛擬類型(X1,X2,...)

如何提高呢?

fun splt (lst: int list) = 
    let 
     fun splt2 (lst: int list, count: int, lst1: int list, lst2: int list) = 
      if null lst 
      then [] 
      else if (count mod 2 = 0) 
       then splt2 (tl lst, count+1, hd lst::lst1, lst2) 
       else splt2 (tl lst, count+1, lst1, hd lst::lst2) 
    in 
     splt2 (lst,1,[],[]) 
    end 

這是我找到的第二個正確實現,但我主要是想修復第一個! I want to split a list into a tupple of odd and even elements

fun split [] = ([], []) 
| split [x] = ([x], []) 
| split (x1::x2::xs) = 
      let 
      val (ys, zs) = split xs 
      in 
      ((x1::ys), (x2::zs)) 
      end; 

更新:改進只是這個替換

if null lst then 
     [] 

if null lst then 
    [lst1]@[lst2] 
+0

我看過你的問題了最後幾天。 SO並不是要教你所有的課程。你將不得不付出更多努力。 – naomik

+0

@naomik但我喜歡SO。我在這裏學到的比在我的班上更多。請分享你的知識。我相信很多人都會從這些小問題中受益。 OMG! –

回答

1

爲了幫助您在您遇到 你需要看的類型錯誤你給的功能

val splt = fn : int list -> 'a list 

問問自己一個列表可以保留什麼?

- val foo = "foo"::(splt[1,2,3,4,5]); 
val foo = ["foo"] : string list 
- val bar = 52::splt[1,2,3,4,5]; 
val bar = [52] : int list 

它可以容納任何東西,但編譯器無法自行判斷。

+0

OMG!我想到了。感謝提示人:)我只需要返回[lst1] @ [lst2]而不是[]。 –

+0

@ Square-root我只是懇求你仔細檢查你的答案的其餘部分:) – matt

+0

這是正確的。我只是測試它:) –

2

下面是你的代碼的一些反饋:

  • 給這個函數一個合適的名字,像splitpartition。我對這些名字的內涵是:分裂(或爆炸)需要的東西,並返回子組件(例如串→字符表)的一個列表,而分區需要的東西名單並根據謂詞分爲兩部分(例如List.partition),但它們並不真正成立。
  • 組成一些不是lst的變量名稱,因爲這只是該類型的縮寫 - 當類型存在時肯定是冗餘的。對於通用方法,好名字可能很難實現。許多ML代碼使用像xs這樣的東西暗示一個通用的複數形式。
  • 溝型註釋;你會得到一個多態函數,更容易讀取:

    fun split input = 
        let 
         fun split' (xys, count, xs, ys) = ... 
        in 
         split' (input, 1, [], []) 
        end 
    
  • 不過說真的,你在網上找到的版本有一定的優勢:模式匹配確保您的列表中有合適的形式被觸發函數體之前,這最大限度地減少運行時錯誤。功能hdtl沒有。

  • 您可以稍微優化案例的順序;即首先列出最常見的情況。圍繞x::xsy::ys的括號是不必要的。另外,其他兩種情況(一種或零種元素)可以簡單組合,但並不重要。

    fun split (x1::x2::xs) = 
        let 
         val (ys, zs) = split xs 
        in 
         (x1::ys, x2::zs) 
        end 
        | split rest = (rest, []) 
    
  • 你也可以使用案例的代替讓-在高端

    fun split (x1::x2::xs) = 
        (case split xs of 
          (ys, zs) => (x1::ys, x2::zs)) 
        | split rest = (rest, []) 
    
  • 最後,您可能希望使此功能尾遞歸:

    fun split xys = 
        let fun split' (x1::x2::xs, ys, zs) = split' (xs, x1::ys, x2::zs) 
          | split' (rest, ys, zs) = (rev (rest @ ys), rev zs) 
        in 
         split' (xys, [], []) 
        end