まず最初に、各演算子が何をするかを知っておく必要があります: :: 個々の要素を既存のリストに入れるので: 1::2::3::[] = [1,2,3] @ 2 つのリストをまとめて次のようにします: [1,2] @ [3,4] = [1,2,3,4]
:: を使用してリストをまとめることもできますが、次のようなリストのリストになります: [1,2] :: [3,4] = [[1,2],[3,4]]
したがって、[x::y] と書くことで、x と y はリスト内のリストになるべきだと言っています。
また、if ステートメントを使用してリストの末尾をチェックするべきではありません。代わりに、次のようにパターンを使用してそれを行うことができます。
fun listofnodes [] = []
| listofnodes ((x,y)::xs) = x :: y :: listofnodes(xs);
最初のパターンは、リストの最後に到達したとき、最後のタプルを抽出すると、 xs がそれ自体を呼び出す空のリストにバインドされていることを保証し、空のリストを残してすべての要素を配置するため、[( 1,2) (3,4) (5,6) (1,5)] は次のように評価されます。
1 :: 2 :: 3 :: 4 :: 5 :: 6 :: 1 :: 5 :: [] = [1,2,3,4,5,6,1,5].
次のようにすることもできます。
fun listofnodes [] = []
| listofnodes ((x,y)::xs) = [x,y] @ listofnodes(xs);
このようにして、各タプルから小さな 2 要素のリストを作成し、これらすべての小さなリストを 1 つの大きなリストにマージします。最後に空のリストは本当に必要ありませんが、再帰がリストの最後で停止し、等号の反対側に何かを配置する必要があることを確認する唯一の方法です。次のように評価します。
[1,2] @ [3,4] @ [5,6] @ [1,5] @ [] = [1,2,3,4,5,6,1,5]。
また、x と y を int としてキャストしますが、実際にキャストする必要はありません。そうしないと、型 " ('a * 'a) list -> 'a list " が取得されます。これは、int を含むすべての入力型で機能することを意味します (タプルに char やint)。あなたはこれを知っていると思いますが、知らない場合のために: ペアと呼ばれるもの (1,2) はタプルと呼ばれます。