2017-03-20 7 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); 

第3行目では、関数が最初の内側リストの要素を再帰的にプルオフし、最終結果にタックします。この最初のリストに何もないときは、それで終わり、2行目はそれを投げ捨てて内側のリストの残りの部分を処理します。処理する内部リストがなくなると、行1の基底ケースに当たって処理が完了します。

mergeSを呼び出すこの関数は、リストのリストを1つのリストに「平らにする」ため、よりイディオム的にflattenと呼ばれます。これは、単一のレベルを平坦化します。あなたはまた、平らにする関数を書くこともできます。 @molbdniloがコメント内で指摘しているように、SMLではネストされたリストを任意のネストレベルにフラット化できる関数を書くことはできません。たとえば、次のような関数を書くことはできません。 [[[1,2]],[[3],[4]]]と同様に[[1],[2],[3],[4]]で動作します.SMLの型システムには任意のネストされたリストに対応する型コンストラクタがないためです。

関連する問題