0

リストを取り込んでリストのリストを返すHaskellコードを書こうとしています。次のコードでこれを行うと、「関数reGroupの非網羅的なパターン」が表示されます。

reGroup :: [[Int]] -> [Int] -> [[Int]]
reGroup [[]] [] = [[]]
reGroup [[]] xs = reGroup [(take 3 xs)] (drop 3 xs)
reGroup [[a]] [] = [[a]]
reGroup [[a]] xs = reGroup [[a], (take 3 xs)] (drop 3 xs)

-- calling the reGroup function from another function as follow
reGroup [[]] [1,2,3,4,5,6,7,8,9]

私が欲しいのは[1,2,3,4,5,6,7,8,9]->[[1,2,3], [4,5,6], [7,8,9]]です。私は何を間違っているのですか、それとも誰かが私にそれへの簡単な方法を教えてもらえますか?

4

5 に答える 5

7

アキュムレータ(最初の引数)なしでこれを実行しようとする方がおそらく簡単です。次に、

groupThree :: [a] -> [[a]] --why only work with Ints?
--if the list begins with three elements, stick them in a group
--then group the remainder of the list
groupThree (a:b:c:more) = [a,b,c]:groupThree more
--grouping an empty list gives you an empty list
groupThree [] = []
--if we have some number of elements less than three
--we can just stick them in a list
groupThree other = [other]

またはドロップアンドテイクを使用して

groupThree :: [a] -> [[a]]
groupThree [] = []
groupThree ls = (take 3 ls):groupThree (drop 3 ls)

これはまったく同じことをします。

コードが機能しない理由は

reGroup [xs,ls] y

どのケースとも一致しません。最初の引数を処理するコードは、1つの要素のみのリストであり、その要素は空のリストまたは1つの要素のみを含むリストです。

アキュムレータの正しい使用法は次のとおりです。

reGroup back [] = back
reGroup back ls = reGroup (back ++ [take 3 ls]) (drop 3 ls)

残念ながら、リストの最後に追加しているため、これは非常に非効率的です(リストの長さに比例して時間がかかります...モジュロ遅延)。代わりに、

reGroup back [] = reverse back
reGroup back ls = reGroup ((take 3 ls):back) (drop 3 ls)

アキュムレータのないバージョンの方が遅いので(そして無限のリストを処理できるので)好きですが。

于 2013-03-07T22:21:05.077 に答える
4
 [[a]]

[[1]]のように、1つの要素を持つリストのみのリストです。

したがって、1回の再帰の後、

reGroup [[]] [1,2,3,4,5,6,7,8,9]

reGroup [[1,2,3]] [4,5,6,7,8,9]

ただし、この場合(3つの要素を持つリストを含むリスト)はパターンが定義されていません。

于 2013-03-07T22:18:05.147 に答える
2

これを試して:

reGroup xs n =
    if drop n xs == []
    then [take n xs]
    else [take n xs] ++ (reGroup (drop n xs) n)

おそらく最も効率的ではありませんが、それは始まりです。

以下を出力します。

> reGroup [1..9]
[[1,2,3],[4,5,6],[7,8,9]]
> reGroup [1..10]
[[1,2,3],[4,5,6],[7,8,9],[10]]

そして、そのエラーが発生する理由は、関数が一致できるすべてのパターンをカバーしていないためです。_ベースケースに1つか2つ入れてみてください。

于 2013-03-07T22:18:02.470 に答える
1

コードをこれに少し変更します

reGroup :: [[Int]] -> [Int] -> [[Int]]; 
reGroup [[]] [] = []; 
reGroup a [] = a; 
reGroup [[]] xs = reGroup [(take 3 xs)] (drop 3 xs); 
reGroup a xs = a ++ reGroup [(take 3 xs)] (drop 3 xs); 

仕事をします。

于 2013-03-07T22:23:58.213 に答える
0
take3 :: [a] -> [[a]]
take3 [] = []
take3 (x:[]) = [[x]]
take3 (x:y:[]) = [[x,y]]
take3 (x:y:z:xs) = [[x,y,z]] ++ take3 xs
于 2013-03-07T22:26:47.093 に答える