2017-03-20 23 views
2

I have a function called mergeP:如何在sml中重複調用另一個函數?

fun mergeP(nil) = nil 
| mergeP(x::[]) = x::[] 
| mergeP(x::y::zs) = (x @ y)::mergeP(zs); 

If mergeP is called like: mergeP([[1],[2],[3],[4]]) it will return [[1,2],[3,4]] . I want to create a function called mergeS that is recursive that repeatedly calls mergeP till the sublist equals just one list. So if mergeS were called like: mergeS([[1],[2],[3],[4]]) it would repeatedly call mergeP till it equals: [1,2,3,4] . Here is my try:

- fun mergeS(nil) = nil 
= |mergeS(xs) = mergeS(mergeP(xs)); 

But this gives me the error:

stdIn:6.1-6.26 Warning: type vars not generalized because of 
    value restriction are instantiated to dummy types (X1,X2,...) 
val it = [] : ?.X1 list 
+1

我不認爲你可以定義一個函數來「移除」SML類型系統中任意數量的列表嵌套層次。 – molbdnilo

回答

2

I believe I got it to work:

fun mergeS(nil) = nil 
| mergeS([xs]) = xs 
| mergeS(xs) = mergeS(mergeP(xs)); 
+0

是的,這確實有效。當你能回答你自己的問題時,這是令人滿意的。 –

0

您的解決方案工作得很好,雖然它可能跳過mergeP和直接定義mergeS

fun mergeS [] = [] 
| mergeS ([]::xss) = mergeS xss 
| mergeS ((x::xs)::xss) = x :: mergeS (xs::xss); 

在第三行中,函數遞歸地拉出第一個內部列表中的元素並將它們粘貼到最終結果上。當第一個列表中沒有任何東西可以完成時,你就完成了,第二行把它扔掉,然後繼續處理剩下的內部列表。當沒有更多的內部列表需要處理時,您在第1行中完成基本案例並完成。

您調用mergeS的這個函數會被更習慣地稱爲flatten,因爲它將列表列表「扁平化」爲一個列表。這使扁平化單一水平。您還可以編寫一個平坦的功能,例如兩個級別(列表到單個列表的列表),但是,正如@molbdnilo在註釋中指出的那樣,在SML中不可能編寫一個可將嵌套列表拼合成任意級別嵌套的函數。你不能寫一個函數,例如將與[[[1,2]],[[3],[4]]]以及[[1],[2],[3],[4]]一起使用,因爲SML的類型系統沒有對應於任意嵌套列表的類型構造函數。

相關問題