リストを取り、関数の出力に基づいて特定の長さのリストのサブセットを構築する関数を書きたいと思います。
ソートされたリスト xs の最初の 50 個の要素に興味があるだけなら、fst (splitAt 50 (sort xs)).
ただし、問題は、リスト内の要素が同じリスト内の他の要素に依存していることです。要素 p を選択した場合、リストの最初の 50 個の要素に含まれていなくても、要素 q と r も選択する必要があります。リストxsから要素aを取得し、要素aとそのすべての必要な要素を含むリストを返す関数finderFuncを使用しています。finderFunc は正常に動作します。ここでの課題は、finderFunc の複数の出力に基づいて合計長が 50 のリストを作成する関数を作成することです。
これが私の試みです:
finish :: [a] -> [a] -> [a]
--This is the base case, which adds nothing to the final list
finish [] fs = []
--The function is recursive, so the fs variable is necessary so that finish
-- can forward the incomplete list to itself.
finish ps fs
-- If the final list fs is too small, add elements to it
| length fs < 50 && length (fs ++ newrs) <= 50 = fs ++ finish newps newrs
-- If the length is met, then add nothing to the list and quit
| length fs >= 50 = finish [] fs
-- These guard statements are currently lacking, not the main problem
| otherwise = finish [] fs
where
--Sort the candidate list
sortedps = sort ps
--(finderFunc a) returns a list of type [a] containing a and all the
-- elements which are required to go with it. This is the interesting
-- bit. rs is also a subset of the candidate list ps.
rs = finderFunc (head sortedps)
--Remove those elements which are already in the final list, because
-- there can be overlap
newrs = filter (`notElem` fs) rs
--Remove the elements we will add to the list from the new list
-- of candidates
newps = filter (`notElem` rs) ps
上記の if ステートメントでは、場合によっては、正確に 50 個の要素のリストが得られないことを認識しています。これは、現在の主な問題ではありません。問題は、関数の終了が期待どおりにまったく機能しないことです。出力リストに重複する要素が生成されるだけでなく、リストに含めたい要素の総数をはるかに超える場合があります。
この書き方では、通常は :finish xs []
のような空のリストで呼び出すので、それが構築するリストは空のリストとして開始されます。